From ef6091a4639dd90a8e723ae74acf6c315ac88f8f Mon Sep 17 00:00:00 2001 From: drdev Date: Tue, 5 Aug 2014 01:28:31 +0000 Subject: [PATCH] Refactor QuestWinLose overlay so most of its code is shared between desktop and mobile --- .gitattributes | 1 + .../forge/screens/match/QuestWinLose.java | 854 ++---------------- .../screens/match/winlose/QuestWinLose.java | 712 +-------------- .../forge/quest/QuestWinLoseController.java | 726 +++++++++++++++ 4 files changed, 802 insertions(+), 1491 deletions(-) create mode 100644 forge-gui/src/main/java/forge/quest/QuestWinLoseController.java diff --git a/.gitattributes b/.gitattributes index 73baa93e723..18617d159ed 100644 --- a/.gitattributes +++ b/.gitattributes @@ -16732,6 +16732,7 @@ forge-gui/src/main/java/forge/quest/QuestSpellShop.java -text forge-gui/src/main/java/forge/quest/QuestUtil.java svneol=native#text/plain forge-gui/src/main/java/forge/quest/QuestUtilCards.java -text forge-gui/src/main/java/forge/quest/QuestUtilUnlockSets.java -text +forge-gui/src/main/java/forge/quest/QuestWinLoseController.java -text forge-gui/src/main/java/forge/quest/QuestWorld.java -text forge-gui/src/main/java/forge/quest/SellRules.java -text forge-gui/src/main/java/forge/quest/StartingPoolPreferences.java -text diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java index 3ac4e9da490..fd805b7b80a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/QuestWinLose.java @@ -16,45 +16,24 @@ */ package forge.screens.match; -import forge.GuiBase; -import forge.LobbyPlayer; -import forge.Singletons; import forge.assets.FSkinProp; -import forge.card.CardEdition; -import forge.card.IUnOpenedProduct; -import forge.card.UnOpenedProduct; import forge.game.Game; -import forge.game.GameEndReason; -import forge.game.GameFormat; -import forge.game.GameOutcome; -import forge.game.player.*; -import forge.gui.GuiChoose; -import forge.gui.SOverlayUtils; -import forge.gui.framework.FScreen; import forge.item.*; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; import forge.quest.*; -import forge.quest.bazaar.QuestItemType; -import forge.quest.data.QuestPreferences; -import forge.quest.data.QuestPreferences.DifficultyPrefs; -import forge.quest.data.QuestPreferences.QPref; import forge.screens.home.quest.CSubmenuChallenges; import forge.screens.home.quest.CSubmenuDuels; import forge.toolbox.FSkin; +import forge.toolbox.FSkin.Colors; +import forge.toolbox.FSkin.SkinColor; import forge.toolbox.FSkin.SkinIcon; import forge.toolbox.FSkin.SkinnedLabel; -import forge.util.MyRandom; -import org.apache.commons.lang3.StringUtils; - -import javax.swing.*; - -import java.awt.*; -import java.util.ArrayList; -import java.util.Collections; +import java.awt.Dimension; import java.util.List; -import java.util.Map.Entry; + +import javax.swing.SwingConstants; /** *

@@ -66,22 +45,16 @@ import java.util.Map.Entry; * */ public class QuestWinLose extends ControlWinLose { - private final transient boolean wonMatch; private final transient ViewWinLose view; - private transient SkinIcon icoTemp; - private transient TitleLabel lblTemp1; - private transient SkinnedLabel lblTemp2; - private final transient boolean isAnte; + private final QuestWinLoseController controller; /** String constraint parameters for title blocks and cardviewer blocks. */ + private static final SkinColor FORE_COLOR = FSkin.getColor(Colors.CLR_TEXT); private static final String CONSTRAINTS_TITLE = "w 95%!, gap 0 0 20px 10px"; private static final String CONSTRAINTS_TEXT = "w 95%!, h 220px!, gap 0 0 0 20px"; private static final String CONSTRAINTS_CARDS = "w 95%!, h 330px!, gap 0 0 0 20px"; private static final String CONSTRAINTS_CARDS_LARGE = "w 95%!, h 600px!, gap 0 0 0 20px"; - private final transient QuestController qData; - private final transient QuestEvent qEvent; - /** * Instantiates a new quest win lose handler. * @@ -90,11 +63,43 @@ public class QuestWinLose extends ControlWinLose { */ public QuestWinLose(final ViewWinLose view0, Game lastGame) { super(view0, lastGame); - this.view = view0; - qData = FModel.getQuest(); - qEvent = qData.getCurrentEvent(); - this.wonMatch = lastGame.getMatch().isWonBy(GuiBase.getInterface().getQuestPlayer()); - this.isAnte = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE); + view = view0; + controller = new QuestWinLoseController(lastGame) { + @Override + protected void showRewards(Runnable runnable) { + runnable.run(); //just run on GUI thread + } + + @Override + protected void showCards(String title, List cards) { + final QuestWinLoseCardViewer cv = new QuestWinLoseCardViewer(cards); + view.getPnlCustom().add(new TitleLabel(title), QuestWinLose.CONSTRAINTS_TITLE); + if (FModel.getPreferences().getPrefBoolean(FPref.UI_LARGE_CARD_VIEWERS)) { + view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS_LARGE); + } + else { + view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS); + } + } + + @Override + protected void showMessage(String message, String title, FSkinProp icon) { + SkinIcon icoTemp = FSkin.getIcon(icon).scale(0.5); + + if (message.contains("\n")) { //ensure new line characters are encoded + message = "" + message.replace("\n", "
") + ""; + } + SkinnedLabel lblMessage = new SkinnedLabel(message); + lblMessage.setFont(FSkin.getFont(14)); + lblMessage.setForeground(FORE_COLOR); + lblMessage.setHorizontalAlignment(SwingConstants.CENTER); + lblMessage.setIconTextGap(50); + lblMessage.setIcon(icoTemp); + + view.getPnlCustom().add(new TitleLabel(title), QuestWinLose.CONSTRAINTS_TITLE); + view.getPnlCustom().add(lblMessage, QuestWinLose.CONSTRAINTS_TEXT); + } + }; } @@ -109,126 +114,10 @@ public class QuestWinLose extends ControlWinLose { */ @Override public final boolean populateCustomPanel() { - this.getView().getBtnRestart().setVisible(false); - QuestController qc = FModel.getQuest(); - - // After the first game, reset the card shop pool to be able to buy back anted cards - if (lastGame.getMatch().getPlayedGames().size() == 1) { - qc.getCards().clearShopList(); - qc.getCards().getShopList(); - } - - final LobbyPlayer questLobbyPlayer = GuiBase.getInterface().getQuestPlayer(); - Player questPlayer = null; - for (Player p : lastGame.getRegisteredPlayers()) { - if (p.getLobbyPlayer().equals(questLobbyPlayer)) { - questPlayer = p; - } - } - if (isAnte) { - //do per-game actions - GameOutcome outcome = lastGame.getOutcome(); - - // Won/lost cards should already be calculated (even in a draw) - GameOutcome.AnteResult anteResult = outcome.anteResult.get(questPlayer); - if (anteResult != null) { - if (anteResult.wonCards != null) - qc.getCards().addAllCards(anteResult.wonCards); - if (anteResult.lostCards != null) - qc.getCards().loseCards(anteResult.lostCards); - this.anteReport(anteResult.wonCards, anteResult.lostCards, questPlayer.equals(outcome.getWinningPlayer())); - } - } - - if (!lastGame.getMatch().isMatchOver()) { - this.getView().getBtnQuit().setText("Quit (-15 Credits)"); - return isAnte; - } else { - this.getView().getBtnContinue().setVisible(false); - if (this.wonMatch) { - this.getView().getBtnQuit().setText("Great!"); - } else { - this.getView().getBtnQuit().setText("OK"); - } - } - - // TODO: We don't have a enum for difficulty? - int difficulty = qData.getAchievements().getDifficulty(); - - - final int wins = qData.getAchievements().getWin(); - // Win case - if (this.wonMatch) { - // Standard event reward credits - this.awardEventCredits(); - - // Challenge reward credits - if (qEvent instanceof QuestEventChallenge) { - this.awardChallengeWin(); - } - - else { - awardSpecialReward("Special bonus reward:"); // If any - // Random rare for winning against a very hard deck - if (qEvent.getDifficulty() == QuestEventDifficulty.EXPERT) { - this.awardRandomRare("You've won a random rare for winning against a very hard deck."); - } - } - - this.awardWinStreakBonus(); - - // Random rare given at 50% chance (65% with luck upgrade) - if (this.getLuckyCoinResult()) { - this.awardRandomRare("You've won a random rare."); - } - - // Award jackpot every 80 games won (currently 10 rares) - - if ((wins > 0) && (((wins + 1) % 80) == 0)) { - this.awardJackpot(); - } - - } - // Lose case - else { - this.penalizeLoss(); - } - - // Grant booster on a win, or on a loss in easy mode - if (this.wonMatch || difficulty == 0) { - final int outcome = this.wonMatch ? wins : qData.getAchievements().getLost(); - int winsPerBooster = FModel.getQuestPreferences().getPrefInt(DifficultyPrefs.WINS_BOOSTER, qData.getAchievements().getDifficulty()); - if (winsPerBooster > 0 && (outcome + 1) % winsPerBooster == 0) { - this.awardBooster(); - } - } - + controller.showRewards(view.getBtnContinue(), view.getBtnRestart(), view.getBtnQuit()); return true; } - private void anteReport(final List cardsWon, List cardsLost, boolean hasWon) { - // Generate Swing components and attach. - if (cardsWon != null && !cardsWon.isEmpty()) { - this.getView().getPnlCustom().add(new TitleLabel("Spoils! These cards will be available in your card pool after this ante match:"), - QuestWinLose.CONSTRAINTS_TITLE); - if (FModel.getPreferences().getPrefBoolean(FPref.UI_LARGE_CARD_VIEWERS)) { - this.getView().getPnlCustom().add(new QuestWinLoseCardViewer(cardsWon), QuestWinLose.CONSTRAINTS_CARDS_LARGE); - } else { - this.getView().getPnlCustom().add(new QuestWinLoseCardViewer(cardsWon), QuestWinLose.CONSTRAINTS_CARDS); - } - } - if (cardsLost != null && !cardsLost.isEmpty()) { - this.getView().getPnlCustom().add(new TitleLabel("Looted! You lost the following cards in an ante match:"), - QuestWinLose.CONSTRAINTS_TITLE); - if (FModel.getPreferences().getPrefBoolean(FPref.UI_LARGE_CARD_VIEWERS)) { - this.getView().getPnlCustom().add(new QuestWinLoseCardViewer(cardsLost), QuestWinLose.CONSTRAINTS_CARDS_LARGE); - } else { - this.getView().getPnlCustom().add(new QuestWinLoseCardViewer(cardsLost), QuestWinLose.CONSTRAINTS_CARDS); - } - } - - } - /** *

* actionOnQuit. @@ -239,649 +128,10 @@ public class QuestWinLose extends ControlWinLose { */ @Override public final void actionOnQuit() { - final int x = FModel.getQuestPreferences().getPrefInt(QPref.PENALTY_LOSS); - - // Record win/loss in quest data - if (this.wonMatch) { - qData.getAchievements().addWin(); - } else { - qData.getAchievements().addLost(); - qData.getAssets().subtractCredits(x); - } - - // Reset cards and zeppelin use - if (qData.getAssets().hasItem(QuestItemType.ZEPPELIN)) { - qData.getAssets().setItemLevel(QuestItemType.ZEPPELIN, 1); - } - - if (qEvent instanceof QuestEventChallenge) { - final String id = ((QuestEventChallenge) qEvent).getId(); - qData.getAchievements().getCurrentChallenges().remove(id); - qData.getAchievements().addLockedChallenge(id); - - // Increment challenge counter to limit challenges available - qData.getAchievements().addChallengesPlayed(); - } - + controller.actionOnQuit(); CSubmenuDuels.SINGLETON_INSTANCE.update(); CSubmenuChallenges.SINGLETON_INSTANCE.update(); - - qData.setCurrentEvent(null); - qData.save(); - FModel.getQuestPreferences().save(); - Singletons.getControl().writeMatchPreferences(); - - Singletons.getControl().endCurrentGame(); - Singletons.getControl().setCurrentScreen(FScreen.HOME_SCREEN); - - SOverlayUtils.hideOverlay(); - } - - /** - *

- * awardEventCredits. - *

- * Generates and displays standard rewards for gameplay and skill level. - * - */ - private void awardEventCredits() { - // TODO use q.qdPrefs to write bonus credits in prefs file - final StringBuilder sb = new StringBuilder(""); - - int credTotal = 0; - int credBase = 0; - int credGameplay = 0; - int credUndefeated = 0; - int credEstates = 0; - - // Basic win bonus - final int base = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_BASE); - double multiplier = 1; - - - switch(qEvent.getDifficulty()) { - case EASY: multiplier = 1; break; - case MEDIUM: multiplier = 1.5; break; - case HARD: multiplier = 2; break; - case EXPERT: multiplier = 3; break; - } - - credBase = (int) (base * multiplier); - - sb.append(StringUtils.capitalize(qEvent.getDifficulty().getTitle())); - sb.append(" opponent: ").append(credBase).append(" credits.
"); - - int creditsForPreviousWins = (int) ((Double.parseDouble(FModel.getQuestPreferences() - .getPref(QPref.REWARDS_WINS_MULTIPLIER)) * qData.getAchievements().getWin())); - credBase += creditsForPreviousWins; - - sb.append("Bonus for previous wins: ").append(creditsForPreviousWins).append( - creditsForPreviousWins != 1 ? " credits.
" : " credit.
"); - - // Gameplay bonuses (for each game win) - boolean hasNeverLost = true; - int lifeDifferenceCredits = 0; - - LobbyPlayer localHuman = GuiBase.getInterface().getQuestPlayer(); - for (final GameOutcome game : lastGame.getMatch().getPlayedGames()) { - if (!game.isWinner(localHuman)) { - hasNeverLost = false; - continue; // no rewards for losing a game - } - // Alternate win - - // final PlayerStatistics aiRating = game.getStatistics(computer.getName()); - PlayerStatistics humanRating = null; - for (Entry kvRating : game) { - if (kvRating.getKey().equals(localHuman)) { - humanRating = kvRating.getValue(); - continue; - } - - final PlayerOutcome outcome = kvRating.getValue().getOutcome(); - final GameLossReason whyAiLost = outcome.lossState; - int altReward = this.getCreditsRewardForAltWin(whyAiLost); - - String winConditionName = "Unknown (bug)"; - if (game.getWinCondition() == GameEndReason.WinsGameSpellEffect) { - winConditionName = game.getWinSpellEffect(); - altReward = this.getCreditsRewardForAltWin(null); - } else { - switch (whyAiLost) { - case Poisoned: - winConditionName = "Poison"; - break; - case Milled: - winConditionName = "Milled"; - break; - case SpellEffect: - winConditionName = outcome.loseConditionSpell; - break; - default: - break; - } - } - - if (altReward > 0) { - credGameplay += altReward; - sb.append(String.format("Alternate win condition: %s! Bonus: %d credits.
", - winConditionName, altReward)); - } - } - // Mulligan to zero - final int cntCardsHumanStartedWith = humanRating.getOpeningHandSize(); - final int mulliganReward = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_MULLIGAN0); - - if (0 == cntCardsHumanStartedWith) { - credGameplay += mulliganReward; - sb.append(String.format("Mulliganed to zero and still won! Bonus: %d credits.
", mulliganReward)); - } - - // Early turn bonus - final int winTurn = game.getLastTurnNumber(); - final int turnCredits = this.getCreditsRewardForWinByTurn(winTurn); - - if (winTurn == 0) { - throw new UnsupportedOperationException("QuestWinLose > " - + "turn calculation error: Zero turn win"); - } else if (winTurn == 1) { - sb.append("Won in one turn!"); - } else if (winTurn <= 5) { - sb.append("Won by turn 5!"); - } else if (winTurn <= 10) { - sb.append("Won by turn 10!"); - } else if (winTurn <= 15) { - sb.append("Won by turn 15!"); - } - - if (turnCredits > 0) { - credGameplay += turnCredits; - sb.append(String.format(" Bonus: %d credits.
", turnCredits)); - } - - if (game.getLifeDelta() >= 50) { - lifeDifferenceCredits += Math.max(Math.min((game.getLifeDelta() - 46) / 4, 750), 0); - } - - } // End for(game) - - if (lifeDifferenceCredits > 0) { - sb.append(String.format("Life total difference: %d credits.
", lifeDifferenceCredits)); - } - - // Undefeated bonus - if (hasNeverLost) { - credUndefeated += FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_UNDEFEATED); - final int reward = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_UNDEFEATED); - sb.append(String.format("You have not lost once! Bonus: %d credits.
", reward)); - } - - // Estates bonus - credTotal = credBase + credGameplay + credUndefeated + lifeDifferenceCredits; - double estateValue = 0; - switch (qData.getAssets().getItemLevel(QuestItemType.ESTATES)) { - case 1: - estateValue = .1; - break; - - case 2: - estateValue = .15; - break; - - case 3: - estateValue = .2; - break; - - default: - break; - } - if (estateValue > 0) { - credEstates = (int) (estateValue * credTotal); - sb.append("Estates bonus: ").append((int) (100 * estateValue)).append("%.
"); - credTotal += credEstates; - } - - // Final output - String congrats = "

"; - if (credTotal < 100) { - congrats += "You've earned"; - } else if (credTotal < 250) { - congrats += "Could be worse: "; - } else if (credTotal < 500) { - congrats += "A respectable"; - } else if (credTotal < 750) { - congrats += "An impressive"; - } else { - congrats += "Spectacular match!"; - } - - sb.append(String.format("%s %d credits in total.

", congrats, credTotal)); - sb.append(""); - qData.getAssets().addCredits(credTotal); - - // Generate Swing components and attach. - this.icoTemp = FSkin.getIcon(FSkinProp.ICO_QUEST_GOLD); - - this.lblTemp1 = new TitleLabel("Gameplay Results"); - - this.lblTemp2 = new SkinnedLabel(sb.toString()); - this.lblTemp2.setHorizontalAlignment(SwingConstants.CENTER); - this.lblTemp2.setFont(FSkin.getFont(14)); - this.lblTemp2.setForeground(Color.white); - this.lblTemp2.setIcon(this.icoTemp); - this.lblTemp2.setIconTextGap(50); - - this.getView().getPnlCustom().add(this.lblTemp1, QuestWinLose.CONSTRAINTS_TITLE); - this.getView().getPnlCustom().add(this.lblTemp2, QuestWinLose.CONSTRAINTS_TEXT); - } - - /** - *

- * awardRandomRare. - *

- * Generates and displays a random rare win case. - * - */ - private void awardRandomRare(final String message) { - final PaperCard c = qData.getCards().addRandomRare(); - final List cardsWon = new ArrayList(); - cardsWon.add(c); - - // Generate Swing components and attach. - this.lblTemp1 = new TitleLabel(message); - - final QuestWinLoseCardViewer cv = new QuestWinLoseCardViewer(cardsWon); - - this.view.getPnlCustom().add(this.lblTemp1, QuestWinLose.CONSTRAINTS_TITLE); - if (FModel.getPreferences().getPrefBoolean(FPref.UI_LARGE_CARD_VIEWERS)) { - this.view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS_LARGE); - } else { - this.view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS); - } - } - - /** - *

- * awardWinStreakBonus. - *

- * Generates and displays a reward for maintaining a win streak. - * - */ - private void awardWinStreakBonus() { - - int currentStreak = (qData.getAchievements().getWinStreakCurrent() + 1) % 50; - - final List cardsWon = new ArrayList<>(); - List cardsToAdd; - String typeWon = ""; - boolean addDraftToken = false; - - switch (currentStreak) { - case 3: - cardsWon.addAll(qData.getCards().addRandomCommon(1)); - typeWon = "common"; - break; - case 5: - cardsWon.addAll(qData.getCards().addRandomUncommon(1)); - typeWon = "uncommon"; - break; - case 7: - cardsWon.addAll(qData.getCards().addRandomRareNotMythic(1)); - typeWon = "rare"; - break; - case 10: - cardsToAdd = qData.getCards().addRandomMythicRare(1); - if (cardsToAdd != null) { - cardsWon.addAll(cardsToAdd); - typeWon = "mythic rare"; - } else { - cardsWon.addAll(qData.getCards().addRandomRareNotMythic(3)); - typeWon = "rare"; - } - break; - case 25: - cardsToAdd = qData.getCards().addRandomMythicRare(5); - if (cardsToAdd != null) { - cardsWon.addAll(cardsToAdd); - typeWon = "mythic rare"; - } else { - cardsWon.addAll(qData.getCards().addRandomRareNotMythic(15)); - typeWon = "rare"; - } - addDraftToken = true; - break; - case 0: //The 50th win in the streak is 0, since (50 % 50 == 0) - cardsToAdd = qData.getCards().addRandomMythicRare(10); - if (cardsToAdd != null) { - cardsWon.addAll(cardsToAdd); - typeWon = "mythic rare"; - } else { - cardsWon.addAll(qData.getCards().addRandomRareNotMythic(30)); - typeWon = "rare"; - } - addDraftToken = true; - break; - default: - return; - } - - if (addDraftToken) { - TitleLabel title = new TitleLabel("Bonus Draft Token Reward"); - SkinnedLabel contents = new SkinnedLabel("For achieving a 25 win streak, you have been awarded a draft token!
Use these tokens to generate new tournaments."); - contents.setHorizontalAlignment(SwingConstants.CENTER); - contents.setFont(FSkin.getFont(14)); - contents.setForeground(Color.white); - contents.setIcon(FSkin.getImage(FSkinProp.ICO_QUEST_COIN)); - contents.setIconTextGap(50); - this.view.getPnlCustom().add(title, QuestWinLose.CONSTRAINTS_TITLE); - this.view.getPnlCustom().add(contents, "w 95%!, h 100px!, gap 0 0 0 20px"); - qData.getAchievements().addDraftToken(); - } - - if (cardsWon.size() > 0) { - this.lblTemp1 = new TitleLabel("You have achieved a " + (currentStreak == 0 ? "50" : currentStreak) + " win streak and won " + cardsWon.size() + " " + typeWon + " card" + ((cardsWon.size() != 1) ? "s" : "") + "!"); - final QuestWinLoseCardViewer cv = new QuestWinLoseCardViewer(cardsWon); - - this.view.getPnlCustom().add(this.lblTemp1, QuestWinLose.CONSTRAINTS_TITLE); - if (FModel.getPreferences().getPrefBoolean(FPref.UI_LARGE_CARD_VIEWERS)) { - this.view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS_LARGE); - } else { - this.view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS); - } - } - - } - - /** - *

- * awardJackpot. - *

- * Generates and displays jackpot win case. - * - */ - private void awardJackpot() { - final List cardsWon = qData.getCards().addRandomRare(10); - - // Generate Swing components and attach. - this.lblTemp1 = new TitleLabel("You just won 10 random rares!"); - final QuestWinLoseCardViewer cv = new QuestWinLoseCardViewer(cardsWon); - - this.view.getPnlCustom().add(this.lblTemp1, QuestWinLose.CONSTRAINTS_TITLE); - if (FModel.getPreferences().getPrefBoolean(FPref.UI_LARGE_CARD_VIEWERS)) { - this.view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS_LARGE); - } else { - this.view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS); - } - } - - /** - *

- * awardBooster. - *

- * Generates and displays booster pack win case. - * - */ - private void awardBooster() { - - List cardsWon = null; - - if (qData.getFormat() == null) { - final List formats = new ArrayList(); - String preferredFormat = FModel.getQuestPreferences().getPref(QPref.BOOSTER_FORMAT); - - GameFormat pref = null; - for (GameFormat f : FModel.getFormats().getOrderedList()) { - formats.add(f); - if (f.toString().equals(preferredFormat)) { - pref = f; - } - } - - Collections.sort(formats); - - final GameFormat selected = GuiChoose.getChoices("Choose bonus booster format", 1, 1, formats, pref, null).get(0); //ch.getSelectedValue(); - FModel.getQuestPreferences().setPref(QPref.BOOSTER_FORMAT, selected.toString()); - - cardsWon = qData.getCards().generateQuestBooster(selected.getFilterPrinted()); - qData.getCards().addAllCards(cardsWon); - - // Generate Swing components and attach. - this.lblTemp1 = new TitleLabel("Bonus booster pack from the \"" + selected.getName() + "\" format!"); - - } else { - final List sets = new ArrayList(); - - for (SealedProduct.Template bd : FModel.getMagicDb().getBoosters()) { - if (bd != null && qData.getFormat().isSetLegal(bd.getEdition())) { - sets.add(bd.getEdition()); - } - } - - int maxChoices = 1; - if (this.wonMatch) { - maxChoices++; - final int wins = qData.getAchievements().getWin(); - if ((wins + 1) % 5 == 0) { maxChoices++; } - if ((wins + 1) % 20 == 0) { maxChoices++; } - if ((wins + 1) % 50 == 0) { maxChoices++; } - maxChoices += qData.getAssets().getItemLevel(QuestItemType.MEMBERSHIP_TOKEN); - } - - List options = new ArrayList(); - - while(!sets.isEmpty() && maxChoices > 0) { - int ix = MyRandom.getRandom().nextInt(sets.size()); - String set = sets.get(ix); - sets.remove(ix); - options.add(FModel.getMagicDb().getEditions().get(set)); - maxChoices--; - } - - final CardEdition chooseEd = GuiChoose.one("Choose bonus booster set:", options); - - IUnOpenedProduct product = new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(chooseEd.getCode())); - cardsWon = product.get(); - qData.getCards().addAllCards(cardsWon); - this.lblTemp1 = new TitleLabel("Bonus " + chooseEd.getName() + " booster pack!"); - } - - if (cardsWon != null) { - // Generate Swing components and attach. - final QuestWinLoseCardViewer cv = new QuestWinLoseCardViewer(cardsWon); - - this.view.getPnlCustom().add(this.lblTemp1, QuestWinLose.CONSTRAINTS_TITLE); - if (FModel.getPreferences().getPrefBoolean(FPref.UI_LARGE_CARD_VIEWERS)) { - this.view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS_LARGE); - } else { - this.view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS); - } - } - - } - - /** - *

- * awardChallengeWin. - *

- * Generates and displays win case for challenge event. - * - */ - private void awardChallengeWin() { - - final long questRewardCredits = ((QuestEventChallenge) qEvent).getCreditsReward(); - - final StringBuilder sb = new StringBuilder(); - sb.append("Challenge completed.

"); - sb.append("Challenge bounty: " + questRewardCredits + " credits."); - - qData.getAssets().addCredits(questRewardCredits); - - // Generate Swing components and attach. - this.icoTemp = FSkin.getIcon(FSkinProp.ICO_QUEST_BOX).scale(0.5); - this.lblTemp1 = new TitleLabel("Challenge Rewards for \"" + ((QuestEventChallenge) qEvent).getTitle() + "\""); - - this.lblTemp2 = new SkinnedLabel(sb.toString()); - this.lblTemp2.setFont(FSkin.getFont(14)); - this.lblTemp2.setForeground(Color.white); - this.lblTemp2.setHorizontalAlignment(SwingConstants.CENTER); - this.lblTemp2.setIconTextGap(50); - this.lblTemp2.setIcon(this.icoTemp); - - this.getView().getPnlCustom().add(this.lblTemp1, QuestWinLose.CONSTRAINTS_TITLE); - this.getView().getPnlCustom().add(this.lblTemp2, QuestWinLose.CONSTRAINTS_TEXT); - - awardSpecialReward(null); - } - - /** - *

- * awardSpecialReward. - *

- * This builds the card reward based on the string data. - * @param message String, reward text to be displayed, if any - */ - private void awardSpecialReward(final String message) { - final List itemsWon = ((QuestEvent) qEvent).getCardRewardList(); - - if (itemsWon == null || itemsWon.isEmpty()) { - return; - } - - final List cardsWon = new ArrayList(); - - for (InventoryItem ii : itemsWon) { - if (ii instanceof PaperCard) { - cardsWon.add((PaperCard) ii); - } else if (ii instanceof TournamentPack || ii instanceof BoosterPack) { - List boosterCards = new ArrayList(); - SealedProduct booster = null; - if (ii instanceof BoosterPack) { - booster = (BoosterPack) ((BoosterPack) ii).clone(); - boosterCards.addAll(booster.getCards()); - } else if (ii instanceof TournamentPack) { - booster = (TournamentPack) ((TournamentPack) ii).clone(); - boosterCards.addAll(booster.getCards()); - } - if (!boosterCards.isEmpty()) { - qData.getCards().addAllCards(boosterCards); - final QuestWinLoseCardViewer cv = new QuestWinLoseCardViewer(boosterCards); - this.view.getPnlCustom().add(new TitleLabel("Extra " + ii.getName() + "!"), QuestWinLose.CONSTRAINTS_TITLE); - if (FModel.getPreferences().getPrefBoolean(FPref.UI_LARGE_CARD_VIEWERS)) { - this.view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS_LARGE); - } else { - this.view.getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS); - } - } - } - else if (ii instanceof IQuestRewardCard) { - final List cardChoices = ((IQuestRewardCard) ii).getChoices(); - final PaperCard chosenCard = (null == cardChoices ? null : GuiChoose.one("Choose " + ((IQuestRewardCard) ii).getName() + ":", cardChoices)); - if (null != chosenCard) { - cardsWon.add(chosenCard); - } - } - } - if (cardsWon != null && !cardsWon.isEmpty()) { - final QuestWinLoseCardViewer cv = new QuestWinLoseCardViewer(cardsWon); - if (message != null) { - this.lblTemp1 = new TitleLabel(message); - this.view.getPnlCustom().add(this.lblTemp1, QuestWinLose.CONSTRAINTS_TITLE); - } - if (FModel.getPreferences().getPrefBoolean(FPref.UI_LARGE_CARD_VIEWERS)) { - this.getView().getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS_LARGE); - } else { - this.getView().getPnlCustom().add(cv, QuestWinLose.CONSTRAINTS_CARDS); - } - qData.getCards().addAllCards(cardsWon); - } - } - - private void penalizeLoss() { - final int x = FModel.getQuestPreferences().getPrefInt(QPref.PENALTY_LOSS); - this.icoTemp = FSkin.getIcon(FSkinProp.ICO_QUEST_HEART).scale(0.5); - - this.lblTemp1 = new TitleLabel("Gameplay Results"); - - this.lblTemp2 = new SkinnedLabel("You lose! You have lost " + x + " credits."); - this.lblTemp2.setFont(FSkin.getFont(14)); - this.lblTemp2.setForeground(Color.white); - this.lblTemp2.setHorizontalAlignment(SwingConstants.CENTER); - this.lblTemp2.setIconTextGap(50); - this.lblTemp2.setIcon(this.icoTemp); - - this.getView().getPnlCustom().add(this.lblTemp1, QuestWinLose.CONSTRAINTS_TITLE); - this.getView().getPnlCustom().add(this.lblTemp2, QuestWinLose.CONSTRAINTS_TEXT); - } - - /** - *

- * getLuckyCoinResult. - *

- * A chance check, for rewards like random rares. - * - * @return boolean - */ - private boolean getLuckyCoinResult() { - final boolean hasCoin = qData.getAssets().getItemLevel(QuestItemType.LUCKY_COIN) >= 1; - - return MyRandom.getRandom().nextFloat() <= (hasCoin ? 0.65f : 0.5f); - } - - /** - *

- * getCreditsRewardForAltWin. - *

- * Retrieves credits for win under special conditions. - * - * @param GameLossReason - * why AI lost - * @return int - */ - private int getCreditsRewardForAltWin(final GameLossReason whyAiLost) { - QuestPreferences qp = FModel.getQuestPreferences(); - if (null == whyAiLost) { - // Felidar, Helix Pinnacle, etc. - return qp.getPrefInt(QPref.REWARDS_ALTERNATIVE); - } - switch (whyAiLost) { - case LifeReachedZero: - return 0; // nothing special here, ordinary kill - case Milled: - return qp.getPrefInt(QPref.REWARDS_MILLED); - case Poisoned: - return qp.getPrefInt(QPref.REWARDS_POISON); - case SpellEffect: // Door to Nothingness, etc. - return qp.getPrefInt(QPref.REWARDS_ALTERNATIVE); - default: - return 0; - } - } - - /** - *

- * getCreditsRewardForWinByTurn. - *

- * Retrieves credits for win on or under turn count. - * - * @param int turn count - * @return int credits won - */ - private int getCreditsRewardForWinByTurn(final int iTurn) { - int credits; - - if (iTurn == 1) { - credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN1); - } else if (iTurn <= 5) { - credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN5); - } else if (iTurn <= 10) { - credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN10); - } else if (iTurn <= 15) { - credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN15); - } else { - credits = 0; - } - - return credits; + super.actionOnQuit(); } /** @@ -892,11 +142,11 @@ public class QuestWinLose extends ControlWinLose { private class TitleLabel extends SkinnedLabel { TitleLabel(final String msg) { super(msg); - this.setFont(FSkin.getFont(16)); - this.setPreferredSize(new Dimension(200, 40)); - this.setHorizontalAlignment(SwingConstants.CENTER); - this.setForeground(Color.white); - this.setBorder(BorderFactory.createMatteBorder(1, 0, 1, 0, Color.white)); + setFont(FSkin.getFont(16)); + setPreferredSize(new Dimension(200, 40)); + setHorizontalAlignment(SwingConstants.CENTER); + setForeground(FORE_COLOR); + setBorder(new FSkin.MatteSkinBorder(1, 0, 1, 0, FORE_COLOR)); } } } diff --git a/forge-gui-mobile/src/forge/screens/match/winlose/QuestWinLose.java b/forge-gui-mobile/src/forge/screens/match/winlose/QuestWinLose.java index 8f0c85998ea..9ad19e44d44 100644 --- a/forge-gui-mobile/src/forge/screens/match/winlose/QuestWinLose.java +++ b/forge-gui-mobile/src/forge/screens/match/winlose/QuestWinLose.java @@ -16,37 +16,16 @@ */ package forge.screens.match.winlose; +import java.util.List; + import forge.FThreads; -import forge.GuiBase; -import forge.LobbyPlayer; import forge.assets.FSkinProp; -import forge.card.CardEdition; -import forge.card.IUnOpenedProduct; -import forge.card.UnOpenedProduct; import forge.game.Game; -import forge.game.GameEndReason; -import forge.game.GameFormat; -import forge.game.GameOutcome; -import forge.game.player.*; -import forge.item.*; -import forge.model.FModel; -import forge.properties.ForgePreferences.FPref; +import forge.item.PaperCard; import forge.quest.*; -import forge.quest.bazaar.QuestItemType; -import forge.quest.data.QuestPreferences; -import forge.quest.data.QuestPreferences.DifficultyPrefs; -import forge.quest.data.QuestPreferences.QPref; -import forge.util.MyRandom; import forge.util.gui.SGuiChoose; import forge.util.gui.SOptionPane; -import org.apache.commons.lang3.StringUtils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map.Entry; - /** *

* QuestWinLose. @@ -57,10 +36,7 @@ import java.util.Map.Entry; * */ public class QuestWinLose extends ControlWinLose { - private final transient boolean wonMatch; - private final transient boolean isAnte; - private final transient QuestController qData; - private final transient QuestEvent qEvent; + private final QuestWinLoseController controller; /** * Instantiates a new quest win lose handler. @@ -70,130 +46,28 @@ public class QuestWinLose extends ControlWinLose { */ public QuestWinLose(final ViewWinLose view0, Game lastGame) { super(view0, lastGame); - qData = FModel.getQuest(); - qEvent = qData.getCurrentEvent(); - wonMatch = lastGame.getMatch().isWonBy(GuiBase.getInterface().getQuestPlayer()); - isAnte = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE); + controller = new QuestWinLoseController(lastGame) { + @Override + protected void showRewards(Runnable runnable) { + //invoke reward logic in background thread so dialogs can be shown + FThreads.invokeInBackgroundThread(runnable); + } + + @Override + protected void showCards(String title, List cards) { + SGuiChoose.reveal(title, cards); + } + + @Override + protected void showMessage(String message, String title, FSkinProp icon) { + SOptionPane.showMessageDialog(message, title, icon); + } + }; } @Override public final void showRewards() { - getView().getBtnRestart().setVisible(false); - final QuestController qc = FModel.getQuest(); - - // After the first game, reset the card shop pool to be able to buy back anted cards - if (lastGame.getMatch().getPlayedGames().size() == 1) { - qc.getCards().clearShopList(); - qc.getCards().getShopList(); - } - - final LobbyPlayer questLobbyPlayer = GuiBase.getInterface().getQuestPlayer(); - Player player = null; - for (Player p : lastGame.getRegisteredPlayers()) { - if (p.getLobbyPlayer().equals(questLobbyPlayer)) { - player = p; - } - } - final Player questPlayer = player; - - final boolean matchIsNotOver = !lastGame.getMatch().isMatchOver(); - if (matchIsNotOver) { - getView().getBtnQuit().setText("Quit (-15 Credits)"); - } - else { - getView().getBtnContinue().setVisible(false); - if (wonMatch) { - getView().getBtnQuit().setText("Great!"); - } - else { - getView().getBtnQuit().setText("OK"); - } - } - - //invoke remaining logic in background thread so dialogs can be shown - FThreads.invokeInBackgroundThread(new Runnable() { - @Override - public void run() { - if (isAnte) { - //do per-game actions - GameOutcome outcome = lastGame.getOutcome(); - - // Won/lost cards should already be calculated (even in a draw) - GameOutcome.AnteResult anteResult = outcome.anteResult.get(questPlayer); - if (anteResult != null) { - if (anteResult.wonCards != null) { - qc.getCards().addAllCards(anteResult.wonCards); - } - if (anteResult.lostCards != null) { - qc.getCards().loseCards(anteResult.lostCards); - } - anteReport(anteResult.wonCards, anteResult.lostCards, questPlayer.equals(outcome.getWinningPlayer())); - } - } - - if (matchIsNotOver) { return; } //skip remaining logic if match isn't over yet - - // TODO: We don't have a enum for difficulty? - int difficulty = qData.getAchievements().getDifficulty(); - - final int wins = qData.getAchievements().getWin(); - // Win case - if (wonMatch) { - // Standard event reward credits - awardEventCredits(); - - // Challenge reward credits - if (qEvent instanceof QuestEventChallenge) { - awardChallengeWin(); - } - - else { - awardSpecialReward("Special bonus reward"); // If any - // Random rare for winning against a very hard deck - if (qEvent.getDifficulty() == QuestEventDifficulty.EXPERT) { - awardRandomRare("You've won a random rare for winning against a very hard deck."); - } - } - - awardWinStreakBonus(); - - // Random rare given at 50% chance (65% with luck upgrade) - if (getLuckyCoinResult()) { - awardRandomRare("You've won a random rare."); - } - - // Award jackpot every 80 games won (currently 10 rares) - - if ((wins > 0) && (((wins + 1) % 80) == 0)) { - awardJackpot(); - } - - } - // Lose case - else { - penalizeLoss(); - } - - // Grant booster on a win, or on a loss in easy mode - if (wonMatch || difficulty == 0) { - final int outcome = wonMatch ? wins : qData.getAchievements().getLost(); - int winsPerBooster = FModel.getQuestPreferences().getPrefInt(DifficultyPrefs.WINS_BOOSTER, qData.getAchievements().getDifficulty()); - if (winsPerBooster > 0 && (outcome + 1) % winsPerBooster == 0) { - awardBooster(); - } - } - } - }); - } - - private void anteReport(final List cardsWon, List cardsLost, boolean hasWon) { - // Generate Swing components and attach. - if (cardsWon != null && !cardsWon.isEmpty()) { - SGuiChoose.reveal("Spoils! Cards won from ante.", cardsWon); - } - if (cardsLost != null && !cardsLost.isEmpty()) { - SGuiChoose.reveal("Looted! Cards lost to ante.", cardsLost); - } + controller.showRewards(getView().getBtnContinue(), getView().getBtnRestart(), getView().getBtnQuit()); } /** @@ -206,547 +80,7 @@ public class QuestWinLose extends ControlWinLose { */ @Override public final void actionOnQuit() { - final int x = FModel.getQuestPreferences().getPrefInt(QPref.PENALTY_LOSS); - - // Record win/loss in quest data - if (wonMatch) { - qData.getAchievements().addWin(); - } - else { - qData.getAchievements().addLost(); - qData.getAssets().subtractCredits(x); - } - - // Reset cards and zeppelin use - if (qData.getAssets().hasItem(QuestItemType.ZEPPELIN)) { - qData.getAssets().setItemLevel(QuestItemType.ZEPPELIN, 1); - } - - if (qEvent instanceof QuestEventChallenge) { - final String id = ((QuestEventChallenge) qEvent).getId(); - qData.getAchievements().getCurrentChallenges().remove(id); - qData.getAchievements().addLockedChallenge(id); - - // Increment challenge counter to limit challenges available - qData.getAchievements().addChallengesPlayed(); - } - - qData.setCurrentEvent(null); - qData.save(); - FModel.getQuestPreferences().save(); + controller.actionOnQuit(); super.actionOnQuit(); } - - /** - *

- * awardEventCredits. - *

- * Generates and displays standard rewards for gameplay and skill level. - * - */ - private void awardEventCredits() { - // TODO use q.qdPrefs to write bonus credits in prefs file - final StringBuilder sb = new StringBuilder(); - - int credTotal = 0; - int credBase = 0; - int credGameplay = 0; - int credUndefeated = 0; - int credEstates = 0; - - // Basic win bonus - final int base = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_BASE); - double multiplier = 1; - - switch (qEvent.getDifficulty()) { - case EASY: multiplier = 1; break; - case MEDIUM: multiplier = 1.5; break; - case HARD: multiplier = 2; break; - case EXPERT: multiplier = 3; break; - } - - credBase = (int) (base * multiplier); - - sb.append(StringUtils.capitalize(qEvent.getDifficulty().getTitle())); - sb.append(" opponent: ").append(credBase).append(" credits.\n"); - - int creditsForPreviousWins = (int) ((Double.parseDouble(FModel.getQuestPreferences() - .getPref(QPref.REWARDS_WINS_MULTIPLIER)) * qData.getAchievements().getWin())); - credBase += creditsForPreviousWins; - - sb.append("Bonus for previous wins: ").append(creditsForPreviousWins).append( - creditsForPreviousWins != 1 ? " credits.\n" : " credit.\n"); - - // Gameplay bonuses (for each game win) - boolean hasNeverLost = true; - int lifeDifferenceCredits = 0; - - LobbyPlayer localHuman = GuiBase.getInterface().getQuestPlayer(); - for (final GameOutcome game : lastGame.getMatch().getPlayedGames()) { - if (!game.isWinner(localHuman)) { - hasNeverLost = false; - continue; // no rewards for losing a game - } - // Alternate win - - // final PlayerStatistics aiRating = game.getStatistics(computer.getName()); - PlayerStatistics humanRating = null; - for (Entry kvRating : game) { - if (kvRating.getKey().equals(localHuman)) { - humanRating = kvRating.getValue(); - continue; - } - - final PlayerOutcome outcome = kvRating.getValue().getOutcome(); - final GameLossReason whyAiLost = outcome.lossState; - int altReward = getCreditsRewardForAltWin(whyAiLost); - - String winConditionName = "Unknown (bug)"; - if (game.getWinCondition() == GameEndReason.WinsGameSpellEffect) { - winConditionName = game.getWinSpellEffect(); - altReward = getCreditsRewardForAltWin(null); - } else { - switch (whyAiLost) { - case Poisoned: - winConditionName = "Poison"; - break; - case Milled: - winConditionName = "Milled"; - break; - case SpellEffect: - winConditionName = outcome.loseConditionSpell; - break; - default: - break; - } - } - - if (altReward > 0) { - credGameplay += altReward; - sb.append(String.format("Alternate win condition: %s! Bonus: %d credits.\n", - winConditionName, altReward)); - } - } - // Mulligan to zero - final int cntCardsHumanStartedWith = humanRating.getOpeningHandSize(); - final int mulliganReward = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_MULLIGAN0); - - if (0 == cntCardsHumanStartedWith) { - credGameplay += mulliganReward; - sb.append(String.format("Mulliganed to zero and still won! Bonus: %d credits.\n", mulliganReward)); - } - - // Early turn bonus - final int winTurn = game.getLastTurnNumber(); - final int turnCredits = getCreditsRewardForWinByTurn(winTurn); - - if (winTurn == 0) { - sb.append("Won on turn zero!"); - } else if (winTurn == 1) { - sb.append("Won in one turn!"); - } else if (winTurn <= 5) { - sb.append("Won by turn 5!"); - } else if (winTurn <= 10) { - sb.append("Won by turn 10!"); - } else if (winTurn <= 15) { - sb.append("Won by turn 15!"); - } - - if (turnCredits > 0) { - credGameplay += turnCredits; - sb.append(String.format(" Bonus: %d credits.\n", turnCredits)); - } - - if (game.getLifeDelta() >= 50) { - lifeDifferenceCredits += Math.max(Math.min((game.getLifeDelta() - 46) / 4, 750), 0); - } - - } // End for(game) - - if (lifeDifferenceCredits > 0) { - sb.append(String.format("Life total difference: %d credits.\n", lifeDifferenceCredits)); - } - - // Undefeated bonus - if (hasNeverLost) { - credUndefeated += FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_UNDEFEATED); - final int reward = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_UNDEFEATED); - sb.append(String.format("You have not lost once! Bonus: %d credits.\n", reward)); - } - - // Estates bonus - credTotal = credBase + credGameplay + credUndefeated + lifeDifferenceCredits; - double estateValue = 0; - switch (qData.getAssets().getItemLevel(QuestItemType.ESTATES)) { - case 1: - estateValue = .1; - break; - - case 2: - estateValue = .15; - break; - - case 3: - estateValue = .2; - break; - - default: - break; - } - if (estateValue > 0) { - credEstates = (int) (estateValue * credTotal); - sb.append("Estates bonus: ").append((int) (100 * estateValue)).append("%.\n"); - credTotal += credEstates; - } - - // Final output - String congrats = "\n"; - if (credTotal < 100) { - congrats += "You've earned"; - } - else if (credTotal < 250) { - congrats += "Could be worse: "; - } - else if (credTotal < 500) { - congrats += "A respectable"; - } - else if (credTotal < 750) { - congrats += "An impressive"; - } - else { - congrats += "Spectacular match!"; - } - - sb.append(String.format("%s %d credits in total.", congrats, credTotal)); - qData.getAssets().addCredits(credTotal); - - SOptionPane.showMessageDialog(sb.toString(), "Gameplay Results", FSkinProp.ICO_QUEST_GOLD); - } - - /** - *

- * awardRandomRare. - *

- * Generates and displays a random rare win case. - * - */ - private void awardRandomRare(final String message) { - final PaperCard c = qData.getCards().addRandomRare(); - final List cardsWon = new ArrayList(); - cardsWon.add(c); - - SGuiChoose.reveal(message, cardsWon); - } - - /** - *

- * awardWinStreakBonus. - *

- * Generates and displays a reward for maintaining a win streak. - * - */ - private void awardWinStreakBonus() { - - int currentStreak = (qData.getAchievements().getWinStreakCurrent() + 1) % 50; - - final List cardsWon = new ArrayList<>(); - List cardsToAdd; - String typeWon = ""; - boolean addDraftToken = false; - - switch (currentStreak) { - case 3: - cardsWon.addAll(qData.getCards().addRandomCommon(1)); - typeWon = "common"; - break; - case 5: - cardsWon.addAll(qData.getCards().addRandomUncommon(1)); - typeWon = "uncommon"; - break; - case 7: - cardsWon.addAll(qData.getCards().addRandomRareNotMythic(1)); - typeWon = "rare"; - break; - case 10: - cardsToAdd = qData.getCards().addRandomMythicRare(1); - if (cardsToAdd != null) { - cardsWon.addAll(cardsToAdd); - typeWon = "mythic rare"; - } else { - cardsWon.addAll(qData.getCards().addRandomRareNotMythic(3)); - typeWon = "rare"; - } - break; - case 25: - cardsToAdd = qData.getCards().addRandomMythicRare(5); - if (cardsToAdd != null) { - cardsWon.addAll(cardsToAdd); - typeWon = "mythic rare"; - } else { - cardsWon.addAll(qData.getCards().addRandomRareNotMythic(15)); - typeWon = "rare"; - } - addDraftToken = true; - break; - case 0: //The 50th win in the streak is 0, since (50 % 50 == 0) - cardsToAdd = qData.getCards().addRandomMythicRare(10); - if (cardsToAdd != null) { - cardsWon.addAll(cardsToAdd); - typeWon = "mythic rare"; - } else { - cardsWon.addAll(qData.getCards().addRandomRareNotMythic(30)); - typeWon = "rare"; - } - addDraftToken = true; - break; - default: - return; - } - - if (addDraftToken) { - SOptionPane.showMessageDialog("For achieving a 25 win streak, you have been awarded a draft token!\nUse these tokens to generate new tournaments.", "Bonus Draft Token Reward", FSkinProp.ICO_QUEST_COIN); - qData.getAchievements().addDraftToken(); - } - - if (cardsWon.size() > 0) { - SGuiChoose.reveal("You have achieved a " + (currentStreak == 0 ? "50" : currentStreak) + " win streak and won " + cardsWon.size() + " " + typeWon + " card" + ((cardsWon.size() != 1) ? "s" : "") + "!", cardsWon); - } - } - - /** - *

- * awardJackpot. - *

- * Generates and displays jackpot win case. - * - */ - private void awardJackpot() { - final List cardsWon = qData.getCards().addRandomRare(10); - SGuiChoose.reveal("You just won 10 random rares!", cardsWon); - } - - /** - *

- * awardBooster. - *

- * Generates and displays booster pack win case. - * - */ - private void awardBooster() { - List cardsWon = null; - - String title; - if (qData.getFormat() == null) { - final List formats = new ArrayList(); - String preferredFormat = FModel.getQuestPreferences().getPref(QPref.BOOSTER_FORMAT); - - GameFormat pref = null; - for (GameFormat f : FModel.getFormats().getOrderedList()) { - formats.add(f); - if (f.toString().equals(preferredFormat)) { - pref = f; - } - } - - Collections.sort(formats); - - final GameFormat selected = SGuiChoose.getChoices("Choose bonus booster format", 1, 1, formats, pref, null).get(0); - FModel.getQuestPreferences().setPref(QPref.BOOSTER_FORMAT, selected.toString()); - - cardsWon = qData.getCards().generateQuestBooster(selected.getFilterPrinted()); - qData.getCards().addAllCards(cardsWon); - - title = "Bonus booster pack from the \"" + selected.getName() + "\" format!"; - } - else { - final List sets = new ArrayList(); - - for (SealedProduct.Template bd : FModel.getMagicDb().getBoosters()) { - if (bd != null && qData.getFormat().isSetLegal(bd.getEdition())) { - sets.add(bd.getEdition()); - } - } - - int maxChoices = 1; - if (wonMatch) { - maxChoices++; - final int wins = qData.getAchievements().getWin(); - if ((wins + 1) % 5 == 0) { maxChoices++; } - if ((wins + 1) % 20 == 0) { maxChoices++; } - if ((wins + 1) % 50 == 0) { maxChoices++; } - maxChoices += qData.getAssets().getItemLevel(QuestItemType.MEMBERSHIP_TOKEN); - } - - List options = new ArrayList(); - - while(!sets.isEmpty() && maxChoices > 0) { - int ix = MyRandom.getRandom().nextInt(sets.size()); - String set = sets.get(ix); - sets.remove(ix); - options.add(FModel.getMagicDb().getEditions().get(set)); - maxChoices--; - } - - final CardEdition chooseEd = SGuiChoose.one("Choose bonus booster set", options); - - IUnOpenedProduct product = new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(chooseEd.getCode())); - cardsWon = product.get(); - qData.getCards().addAllCards(cardsWon); - title = "Bonus " + chooseEd.getName() + " booster pack!"; - } - - if (cardsWon != null) { - SGuiChoose.reveal(title, cardsWon); - } - } - - /** - *

- * awardChallengeWin. - *

- * Generates and displays win case for challenge event. - * - */ - private void awardChallengeWin() { - final long questRewardCredits = ((QuestEventChallenge) qEvent).getCreditsReward(); - - final StringBuilder sb = new StringBuilder(); - sb.append("Challenge completed.\n\n"); - sb.append("Challenge bounty: " + questRewardCredits + " credits."); - - qData.getAssets().addCredits(questRewardCredits); - - SOptionPane.showMessageDialog(sb.toString(), "Challenge Rewards for \"" + ((QuestEventChallenge) qEvent).getTitle() + "\"", FSkinProp.ICO_QUEST_BOX); - - awardSpecialReward(null); - } - - /** - *

- * awardSpecialReward. - *

- * This builds the card reward based on the string data. - * @param message String, reward text to be displayed, if any - */ - private void awardSpecialReward(String message) { - final List itemsWon = ((QuestEvent) qEvent).getCardRewardList(); - - if (itemsWon == null || itemsWon.isEmpty()) { - return; - } - - final List cardsWon = new ArrayList(); - - for (InventoryItem ii : itemsWon) { - if (ii instanceof PaperCard) { - cardsWon.add((PaperCard) ii); - } - else if (ii instanceof TournamentPack || ii instanceof BoosterPack) { - List boosterCards = new ArrayList(); - SealedProduct booster = null; - if (ii instanceof BoosterPack) { - booster = (BoosterPack) ((BoosterPack) ii).clone(); - boosterCards.addAll(booster.getCards()); - } - else if (ii instanceof TournamentPack) { - booster = (TournamentPack) ((TournamentPack) ii).clone(); - boosterCards.addAll(booster.getCards()); - } - if (!boosterCards.isEmpty()) { - qData.getCards().addAllCards(boosterCards); - SGuiChoose.reveal("Extra " + ii.getName() + "!", boosterCards); - } - } - else if (ii instanceof IQuestRewardCard) { - final List cardChoices = ((IQuestRewardCard) ii).getChoices(); - final PaperCard chosenCard = (null == cardChoices ? null : SGuiChoose.one("Choose " + ((IQuestRewardCard) ii).getName(), cardChoices)); - if (null != chosenCard) { - cardsWon.add(chosenCard); - } - } - } - if (cardsWon != null && !cardsWon.isEmpty()) { - if (message == null) { - message = "Cards Won"; - } - SGuiChoose.reveal(message, cardsWon); - qData.getCards().addAllCards(cardsWon); - } - } - - private void penalizeLoss() { - final int x = FModel.getQuestPreferences().getPrefInt(QPref.PENALTY_LOSS); - SOptionPane.showMessageDialog("You lose! You have lost " + x + " credits.", "Gameplay Results", FSkinProp.ICO_QUEST_HEART); - } - - /** - *

- * getLuckyCoinResult. - *

- * A chance check, for rewards like random rares. - * - * @return boolean - */ - private boolean getLuckyCoinResult() { - final boolean hasCoin = qData.getAssets().getItemLevel(QuestItemType.LUCKY_COIN) >= 1; - - return MyRandom.getRandom().nextFloat() <= (hasCoin ? 0.65f : 0.5f); - } - - /** - *

- * getCreditsRewardForAltWin. - *

- * Retrieves credits for win under special conditions. - * - * @param GameLossReason - * why AI lost - * @return int - */ - private int getCreditsRewardForAltWin(final GameLossReason whyAiLost) { - QuestPreferences qp = FModel.getQuestPreferences(); - if (null == whyAiLost) { - // Felidar, Helix Pinnacle, etc. - return qp.getPrefInt(QPref.REWARDS_ALTERNATIVE); - } - switch (whyAiLost) { - case LifeReachedZero: - return 0; // nothing special here, ordinary kill - case Milled: - return qp.getPrefInt(QPref.REWARDS_MILLED); - case Poisoned: - return qp.getPrefInt(QPref.REWARDS_POISON); - case SpellEffect: // Door to Nothingness, etc. - return qp.getPrefInt(QPref.REWARDS_ALTERNATIVE); - default: - return 0; - } - } - - /** - *

- * getCreditsRewardForWinByTurn. - *

- * Retrieves credits for win on or under turn count. - * - * @param int turn count - * @return int credits won - */ - private int getCreditsRewardForWinByTurn(final int iTurn) { - int credits; - - if (iTurn <= 1) { - credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN1); - } else if (iTurn <= 5) { - credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN5); - } else if (iTurn <= 10) { - credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN10); - } else if (iTurn <= 15) { - credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN15); - } else { - credits = 0; - } - - return credits; - } } diff --git a/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java b/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java new file mode 100644 index 00000000000..ac8661a585b --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/QuestWinLoseController.java @@ -0,0 +1,726 @@ +package forge.quest; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; + +import org.apache.commons.lang3.StringUtils; + +import forge.GuiBase; +import forge.LobbyPlayer; +import forge.assets.FSkinProp; +import forge.card.CardEdition; +import forge.card.IUnOpenedProduct; +import forge.card.UnOpenedProduct; +import forge.game.Game; +import forge.game.GameEndReason; +import forge.game.GameFormat; +import forge.game.GameOutcome; +import forge.game.player.GameLossReason; +import forge.game.player.Player; +import forge.game.player.PlayerOutcome; +import forge.game.player.PlayerStatistics; +import forge.interfaces.IButton; +import forge.item.BoosterPack; +import forge.item.InventoryItem; +import forge.item.PaperCard; +import forge.item.SealedProduct; +import forge.item.TournamentPack; +import forge.model.FModel; +import forge.properties.ForgePreferences.FPref; +import forge.quest.bazaar.QuestItemType; +import forge.quest.data.QuestPreferences; +import forge.quest.data.QuestPreferences.DifficultyPrefs; +import forge.quest.data.QuestPreferences.QPref; +import forge.util.MyRandom; +import forge.util.gui.SGuiChoose; + +public abstract class QuestWinLoseController { + private final Game lastGame; + private final transient boolean wonMatch; + private final transient boolean isAnte; + private final transient QuestController qData; + private final transient QuestEvent qEvent; + + public QuestWinLoseController(Game lastGame0) { + lastGame = lastGame0; + qData = FModel.getQuest(); + qEvent = qData.getCurrentEvent(); + wonMatch = lastGame.getMatch().isWonBy(GuiBase.getInterface().getQuestPlayer()); + isAnte = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE); + } + + public void showRewards(final IButton btnContinue, final IButton btnRestart, final IButton btnQuit) { + btnRestart.setVisible(false); + final QuestController qc = FModel.getQuest(); + + // After the first game, reset the card shop pool to be able to buy back anted cards + if (lastGame.getMatch().getPlayedGames().size() == 1) { + qc.getCards().clearShopList(); + qc.getCards().getShopList(); + } + + final LobbyPlayer questLobbyPlayer = GuiBase.getInterface().getQuestPlayer(); + Player player = null; + for (Player p : lastGame.getRegisteredPlayers()) { + if (p.getLobbyPlayer().equals(questLobbyPlayer)) { + player = p; + } + } + final Player questPlayer = player; + + final boolean matchIsNotOver = !lastGame.getMatch().isMatchOver(); + if (matchIsNotOver) { + btnQuit.setText("Quit (-15 Credits)"); + } + else { + btnContinue.setVisible(false); + if (wonMatch) { + btnQuit.setText("Great!"); + } + else { + btnQuit.setText("OK"); + } + } + + //give controller a chance to run remaining logic on a separate thread + showRewards(new Runnable() { + @Override + public void run() { + if (isAnte) { + //do per-game actions + GameOutcome outcome = lastGame.getOutcome(); + + // Won/lost cards should already be calculated (even in a draw) + GameOutcome.AnteResult anteResult = outcome.anteResult.get(questPlayer); + if (anteResult != null) { + if (anteResult.wonCards != null) { + qc.getCards().addAllCards(anteResult.wonCards); + } + if (anteResult.lostCards != null) { + qc.getCards().loseCards(anteResult.lostCards); + } + anteReport(anteResult.wonCards, anteResult.lostCards, questPlayer.equals(outcome.getWinningPlayer())); + } + } + + if (matchIsNotOver) { return; } //skip remaining logic if match isn't over yet + + // TODO: We don't have a enum for difficulty? + int difficulty = qData.getAchievements().getDifficulty(); + + final int wins = qData.getAchievements().getWin(); + // Win case + if (wonMatch) { + // Standard event reward credits + awardEventCredits(); + + // Challenge reward credits + if (qEvent instanceof QuestEventChallenge) { + awardChallengeWin(); + } + + else { + awardSpecialReward("Special bonus reward"); // If any + // Random rare for winning against a very hard deck + if (qEvent.getDifficulty() == QuestEventDifficulty.EXPERT) { + awardRandomRare("You've won a random rare for winning against a very hard deck."); + } + } + + awardWinStreakBonus(); + + // Random rare given at 50% chance (65% with luck upgrade) + if (getLuckyCoinResult()) { + awardRandomRare("You've won a random rare."); + } + + // Award jackpot every 80 games won (currently 10 rares) + + if ((wins > 0) && (((wins + 1) % 80) == 0)) { + awardJackpot(); + } + + } + // Lose case + else { + penalizeLoss(); + } + + // Grant booster on a win, or on a loss in easy mode + if (wonMatch || difficulty == 0) { + final int outcome = wonMatch ? wins : qData.getAchievements().getLost(); + int winsPerBooster = FModel.getQuestPreferences().getPrefInt(DifficultyPrefs.WINS_BOOSTER, qData.getAchievements().getDifficulty()); + if (winsPerBooster > 0 && (outcome + 1) % winsPerBooster == 0) { + awardBooster(); + } + } + } + }); + } + + private void anteReport(final List cardsWon, List cardsLost, boolean hasWon) { + // Generate Swing components and attach. + if (cardsWon != null && !cardsWon.isEmpty()) { + showCards("Spoils! Cards won from ante.", cardsWon); + } + if (cardsLost != null && !cardsLost.isEmpty()) { + showCards("Looted! Cards lost to ante.", cardsLost); + } + } + + public void actionOnQuit() { + final int x = FModel.getQuestPreferences().getPrefInt(QPref.PENALTY_LOSS); + + // Record win/loss in quest data + if (wonMatch) { + qData.getAchievements().addWin(); + } + else { + qData.getAchievements().addLost(); + qData.getAssets().subtractCredits(x); + } + + // Reset cards and zeppelin use + if (qData.getAssets().hasItem(QuestItemType.ZEPPELIN)) { + qData.getAssets().setItemLevel(QuestItemType.ZEPPELIN, 1); + } + + if (qEvent instanceof QuestEventChallenge) { + final String id = ((QuestEventChallenge) qEvent).getId(); + qData.getAchievements().getCurrentChallenges().remove(id); + qData.getAchievements().addLockedChallenge(id); + + // Increment challenge counter to limit challenges available + qData.getAchievements().addChallengesPlayed(); + } + + qData.setCurrentEvent(null); + qData.save(); + FModel.getQuestPreferences().save(); + } + + + /** + *

+ * awardEventCredits. + *

+ * Generates and displays standard rewards for gameplay and skill level. + * + */ + private void awardEventCredits() { + // TODO use q.qdPrefs to write bonus credits in prefs file + final StringBuilder sb = new StringBuilder(); + + int credTotal = 0; + int credBase = 0; + int credGameplay = 0; + int credUndefeated = 0; + int credEstates = 0; + + // Basic win bonus + final int base = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_BASE); + double multiplier = 1; + + switch (qEvent.getDifficulty()) { + case EASY: multiplier = 1; break; + case MEDIUM: multiplier = 1.5; break; + case HARD: multiplier = 2; break; + case EXPERT: multiplier = 3; break; + } + + credBase = (int) (base * multiplier); + + sb.append(StringUtils.capitalize(qEvent.getDifficulty().getTitle())); + sb.append(" opponent: ").append(credBase).append(" credits.\n"); + + int creditsForPreviousWins = (int) ((Double.parseDouble(FModel.getQuestPreferences() + .getPref(QPref.REWARDS_WINS_MULTIPLIER)) * qData.getAchievements().getWin())); + credBase += creditsForPreviousWins; + + sb.append("Bonus for previous wins: ").append(creditsForPreviousWins).append( + creditsForPreviousWins != 1 ? " credits.\n" : " credit.\n"); + + // Gameplay bonuses (for each game win) + boolean hasNeverLost = true; + int lifeDifferenceCredits = 0; + + LobbyPlayer localHuman = GuiBase.getInterface().getQuestPlayer(); + for (final GameOutcome game : lastGame.getMatch().getPlayedGames()) { + if (!game.isWinner(localHuman)) { + hasNeverLost = false; + continue; // no rewards for losing a game + } + // Alternate win + + // final PlayerStatistics aiRating = game.getStatistics(computer.getName()); + PlayerStatistics humanRating = null; + for (Entry kvRating : game) { + if (kvRating.getKey().equals(localHuman)) { + humanRating = kvRating.getValue(); + continue; + } + + final PlayerOutcome outcome = kvRating.getValue().getOutcome(); + final GameLossReason whyAiLost = outcome.lossState; + int altReward = getCreditsRewardForAltWin(whyAiLost); + + String winConditionName = "Unknown (bug)"; + if (game.getWinCondition() == GameEndReason.WinsGameSpellEffect) { + winConditionName = game.getWinSpellEffect(); + altReward = getCreditsRewardForAltWin(null); + } + else { + switch (whyAiLost) { + case Poisoned: + winConditionName = "Poison"; + break; + case Milled: + winConditionName = "Milled"; + break; + case SpellEffect: + winConditionName = outcome.loseConditionSpell; + break; + default: + break; + } + } + + if (altReward > 0) { + credGameplay += altReward; + sb.append(String.format("Alternate win condition: %s! Bonus: %d credits.\n", + winConditionName, altReward)); + } + } + // Mulligan to zero + final int cntCardsHumanStartedWith = humanRating.getOpeningHandSize(); + final int mulliganReward = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_MULLIGAN0); + + if (0 == cntCardsHumanStartedWith) { + credGameplay += mulliganReward; + sb.append(String.format("Mulliganed to zero and still won! Bonus: %d credits.\n", mulliganReward)); + } + + // Early turn bonus + final int winTurn = game.getLastTurnNumber(); + final int turnCredits = getCreditsRewardForWinByTurn(winTurn); + + if (winTurn == 0) { + sb.append("Won on turn zero!"); + } + else if (winTurn == 1) { + sb.append("Won in one turn!"); + } + else if (winTurn <= 5) { + sb.append("Won by turn 5!"); + } + else if (winTurn <= 10) { + sb.append("Won by turn 10!"); + } + else if (winTurn <= 15) { + sb.append("Won by turn 15!"); + } + + if (turnCredits > 0) { + credGameplay += turnCredits; + sb.append(String.format(" Bonus: %d credits.\n", turnCredits)); + } + + if (game.getLifeDelta() >= 50) { + lifeDifferenceCredits += Math.max(Math.min((game.getLifeDelta() - 46) / 4, 750), 0); + } + + } // End for(game) + + if (lifeDifferenceCredits > 0) { + sb.append(String.format("Life total difference: %d credits.\n", lifeDifferenceCredits)); + } + + // Undefeated bonus + if (hasNeverLost) { + credUndefeated += FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_UNDEFEATED); + final int reward = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_UNDEFEATED); + sb.append(String.format("You have not lost once! Bonus: %d credits.\n", reward)); + } + + // Estates bonus + credTotal = credBase + credGameplay + credUndefeated + lifeDifferenceCredits; + double estateValue = 0; + switch (qData.getAssets().getItemLevel(QuestItemType.ESTATES)) { + case 1: + estateValue = .1; + break; + case 2: + estateValue = .15; + break; + case 3: + estateValue = .2; + break; + default: + break; + } + if (estateValue > 0) { + credEstates = (int) (estateValue * credTotal); + sb.append("Estates bonus: ").append((int) (100 * estateValue)).append("%.\n"); + credTotal += credEstates; + } + + // Final output + String congrats = "\n"; + if (credTotal < 100) { + congrats += "You've earned"; + } + else if (credTotal < 250) { + congrats += "Could be worse: "; + } + else if (credTotal < 500) { + congrats += "A respectable"; + } + else if (credTotal < 750) { + congrats += "An impressive"; + } + else { + congrats += "Spectacular match!"; + } + + sb.append(String.format("%s %d credits in total.", congrats, credTotal)); + qData.getAssets().addCredits(credTotal); + + showMessage(sb.toString(), "Gameplay Results", FSkinProp.ICO_QUEST_GOLD); + } + + /** + *

+ * awardRandomRare. + *

+ * Generates and displays a random rare win case. + * + */ + private void awardRandomRare(final String message) { + final PaperCard c = qData.getCards().addRandomRare(); + final List cardsWon = new ArrayList(); + cardsWon.add(c); + + showCards(message, cardsWon); + } + + /** + *

+ * awardWinStreakBonus. + *

+ * Generates and displays a reward for maintaining a win streak. + * + */ + private void awardWinStreakBonus() { + int currentStreak = (qData.getAchievements().getWinStreakCurrent() + 1) % 50; + + final List cardsWon = new ArrayList<>(); + List cardsToAdd; + String typeWon = ""; + boolean addDraftToken = false; + + switch (currentStreak) { + case 3: + cardsWon.addAll(qData.getCards().addRandomCommon(1)); + typeWon = "common"; + break; + case 5: + cardsWon.addAll(qData.getCards().addRandomUncommon(1)); + typeWon = "uncommon"; + break; + case 7: + cardsWon.addAll(qData.getCards().addRandomRareNotMythic(1)); + typeWon = "rare"; + break; + case 10: + cardsToAdd = qData.getCards().addRandomMythicRare(1); + if (cardsToAdd != null) { + cardsWon.addAll(cardsToAdd); + typeWon = "mythic rare"; + } else { + cardsWon.addAll(qData.getCards().addRandomRareNotMythic(3)); + typeWon = "rare"; + } + break; + case 25: + cardsToAdd = qData.getCards().addRandomMythicRare(5); + if (cardsToAdd != null) { + cardsWon.addAll(cardsToAdd); + typeWon = "mythic rare"; + } else { + cardsWon.addAll(qData.getCards().addRandomRareNotMythic(15)); + typeWon = "rare"; + } + addDraftToken = true; + break; + case 0: //The 50th win in the streak is 0, since (50 % 50 == 0) + cardsToAdd = qData.getCards().addRandomMythicRare(10); + if (cardsToAdd != null) { + cardsWon.addAll(cardsToAdd); + typeWon = "mythic rare"; + } else { + cardsWon.addAll(qData.getCards().addRandomRareNotMythic(30)); + typeWon = "rare"; + } + addDraftToken = true; + break; + default: + return; + } + + if (addDraftToken) { + showMessage("For achieving a 25 win streak, you have been awarded a draft token!\nUse these tokens to generate new tournaments.", "Bonus Draft Token Reward", FSkinProp.ICO_QUEST_COIN); + qData.getAchievements().addDraftToken(); + } + + if (cardsWon.size() > 0) { + showCards("You have achieved a " + (currentStreak == 0 ? "50" : currentStreak) + " win streak and won " + cardsWon.size() + " " + typeWon + " card" + ((cardsWon.size() != 1) ? "s" : "") + "!", cardsWon); + } + } + + /** + *

+ * awardJackpot. + *

+ * Generates and displays jackpot win case. + * + */ + private void awardJackpot() { + final List cardsWon = qData.getCards().addRandomRare(10); + showCards("You just won 10 random rares!", cardsWon); + } + + /** + *

+ * awardBooster. + *

+ * Generates and displays booster pack win case. + * + */ + private void awardBooster() { + List cardsWon = null; + + String title; + if (qData.getFormat() == null) { + final List formats = new ArrayList(); + String preferredFormat = FModel.getQuestPreferences().getPref(QPref.BOOSTER_FORMAT); + + GameFormat pref = null; + for (GameFormat f : FModel.getFormats().getOrderedList()) { + formats.add(f); + if (f.toString().equals(preferredFormat)) { + pref = f; + } + } + + Collections.sort(formats); + + final GameFormat selected = SGuiChoose.getChoices("Choose bonus booster format", 1, 1, formats, pref, null).get(0); + FModel.getQuestPreferences().setPref(QPref.BOOSTER_FORMAT, selected.toString()); + + cardsWon = qData.getCards().generateQuestBooster(selected.getFilterPrinted()); + qData.getCards().addAllCards(cardsWon); + + title = "Bonus booster pack from the \"" + selected.getName() + "\" format!"; + } + else { + final List sets = new ArrayList(); + + for (SealedProduct.Template bd : FModel.getMagicDb().getBoosters()) { + if (bd != null && qData.getFormat().isSetLegal(bd.getEdition())) { + sets.add(bd.getEdition()); + } + } + + int maxChoices = 1; + if (wonMatch) { + maxChoices++; + final int wins = qData.getAchievements().getWin(); + if ((wins + 1) % 5 == 0) { maxChoices++; } + if ((wins + 1) % 20 == 0) { maxChoices++; } + if ((wins + 1) % 50 == 0) { maxChoices++; } + maxChoices += qData.getAssets().getItemLevel(QuestItemType.MEMBERSHIP_TOKEN); + } + + List options = new ArrayList(); + + while(!sets.isEmpty() && maxChoices > 0) { + int ix = MyRandom.getRandom().nextInt(sets.size()); + String set = sets.get(ix); + sets.remove(ix); + options.add(FModel.getMagicDb().getEditions().get(set)); + maxChoices--; + } + + final CardEdition chooseEd = SGuiChoose.one("Choose bonus booster set", options); + + IUnOpenedProduct product = new UnOpenedProduct(FModel.getMagicDb().getBoosters().get(chooseEd.getCode())); + cardsWon = product.get(); + qData.getCards().addAllCards(cardsWon); + title = "Bonus " + chooseEd.getName() + " booster pack!"; + } + + if (cardsWon != null) { + showCards(title, cardsWon); + } + } + + /** + *

+ * awardChallengeWin. + *

+ * Generates and displays win case for challenge event. + * + */ + private void awardChallengeWin() { + final long questRewardCredits = ((QuestEventChallenge) qEvent).getCreditsReward(); + + final StringBuilder sb = new StringBuilder(); + sb.append("Challenge completed.\n\n"); + sb.append("Challenge bounty: " + questRewardCredits + " credits."); + + qData.getAssets().addCredits(questRewardCredits); + + showMessage(sb.toString(), "Challenge Rewards for \"" + ((QuestEventChallenge) qEvent).getTitle() + "\"", FSkinProp.ICO_QUEST_BOX); + + awardSpecialReward(null); + } + + /** + *

+ * awardSpecialReward. + *

+ * This builds the card reward based on the string data. + * @param message String, reward text to be displayed, if any + */ + private void awardSpecialReward(String message) { + final List itemsWon = ((QuestEvent) qEvent).getCardRewardList(); + + if (itemsWon == null || itemsWon.isEmpty()) { + return; + } + + final List cardsWon = new ArrayList(); + + for (InventoryItem ii : itemsWon) { + if (ii instanceof PaperCard) { + cardsWon.add((PaperCard) ii); + } + else if (ii instanceof TournamentPack || ii instanceof BoosterPack) { + List boosterCards = new ArrayList(); + SealedProduct booster = null; + if (ii instanceof BoosterPack) { + booster = (BoosterPack) ((BoosterPack) ii).clone(); + boosterCards.addAll(booster.getCards()); + } + else if (ii instanceof TournamentPack) { + booster = (TournamentPack) ((TournamentPack) ii).clone(); + boosterCards.addAll(booster.getCards()); + } + if (!boosterCards.isEmpty()) { + qData.getCards().addAllCards(boosterCards); + showCards("Extra " + ii.getName() + "!", boosterCards); + } + } + else if (ii instanceof IQuestRewardCard) { + final List cardChoices = ((IQuestRewardCard) ii).getChoices(); + final PaperCard chosenCard = (null == cardChoices ? null : SGuiChoose.one("Choose " + ((IQuestRewardCard) ii).getName(), cardChoices)); + if (null != chosenCard) { + cardsWon.add(chosenCard); + } + } + } + if (cardsWon != null && !cardsWon.isEmpty()) { + if (message == null) { + message = "Cards Won"; + } + showCards(message, cardsWon); + qData.getCards().addAllCards(cardsWon); + } + } + + private void penalizeLoss() { + final int x = FModel.getQuestPreferences().getPrefInt(QPref.PENALTY_LOSS); + showMessage("You lose! You have lost " + x + " credits.", "Gameplay Results", FSkinProp.ICO_QUEST_HEART); + } + + /** + *

+ * getLuckyCoinResult. + *

+ * A chance check, for rewards like random rares. + * + * @return boolean + */ + private boolean getLuckyCoinResult() { + final boolean hasCoin = qData.getAssets().getItemLevel(QuestItemType.LUCKY_COIN) >= 1; + + return MyRandom.getRandom().nextFloat() <= (hasCoin ? 0.65f : 0.5f); + } + + /** + *

+ * getCreditsRewardForAltWin. + *

+ * Retrieves credits for win under special conditions. + * + * @param GameLossReason + * why AI lost + * @return int + */ + private int getCreditsRewardForAltWin(final GameLossReason whyAiLost) { + QuestPreferences qp = FModel.getQuestPreferences(); + if (null == whyAiLost) { + // Felidar, Helix Pinnacle, etc. + return qp.getPrefInt(QPref.REWARDS_ALTERNATIVE); + } + switch (whyAiLost) { + case LifeReachedZero: + return 0; // nothing special here, ordinary kill + case Milled: + return qp.getPrefInt(QPref.REWARDS_MILLED); + case Poisoned: + return qp.getPrefInt(QPref.REWARDS_POISON); + case SpellEffect: // Door to Nothingness, etc. + return qp.getPrefInt(QPref.REWARDS_ALTERNATIVE); + default: + return 0; + } + } + + /** + *

+ * getCreditsRewardForWinByTurn. + *

+ * Retrieves credits for win on or under turn count. + * + * @param int turn count + * @return int credits won + */ + private int getCreditsRewardForWinByTurn(final int iTurn) { + int credits; + + if (iTurn <= 1) { + credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN1); + } + else if (iTurn <= 5) { + credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN5); + } + else if (iTurn <= 10) { + credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN10); + } + else if (iTurn <= 15) { + credits = FModel.getQuestPreferences().getPrefInt(QPref.REWARDS_TURN15); + } + else { + credits = 0; + } + + return credits; + } + + protected abstract void showRewards(Runnable runnable); + protected abstract void showCards(String title, List cards); + protected abstract void showMessage(String message, String title, FSkinProp icon); +}