diff --git a/.gitattributes b/.gitattributes index 23d96f5ce2b..f100adc7647 100644 --- a/.gitattributes +++ b/.gitattributes @@ -16702,6 +16702,7 @@ forge-gui/src/main/java/forge/quest/QuestMode.java -text forge-gui/src/main/java/forge/quest/QuestRewardCard.java -text forge-gui/src/main/java/forge/quest/QuestRewardCardDuplicate.java -text forge-gui/src/main/java/forge/quest/QuestRewardCardFiltered.java -text +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 diff --git a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java index 885243e91d1..ce9b5762d47 100644 --- a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java +++ b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java @@ -44,6 +44,7 @@ import forge.game.player.Player; import forge.game.player.RegisteredPlayer; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; +import forge.gui.BoxedProductCardListViewer; import forge.gui.CardListViewer; import forge.gui.FNetOverlay; import forge.gui.GuiChoose; @@ -173,6 +174,14 @@ public class GuiDesktop implements IGuiBase { cardView.dispose(); } + @Override + public boolean showBoxedProduct(final String title, final String message, final List list) { + final BoxedProductCardListViewer viewer = new BoxedProductCardListViewer(title, message, list); + viewer.setVisible(true); + viewer.dispose(); + return viewer.skipTheRest(); + } + @Override public IButton getBtnOK() { return VMatchUI.SINGLETON_INSTANCE.getBtnOK(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestCardShop.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestCardShop.java index 1e8de1acaf7..92f792e882c 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestCardShop.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CEditorQuestCardShop.java @@ -17,45 +17,28 @@ */ package forge.screens.deckeditor.controllers; -import com.google.common.base.Function; - import forge.UiCommand; import forge.assets.FSkinProp; -import forge.deck.CardPool; -import forge.deck.Deck; import forge.deck.DeckBase; -import forge.deck.DeckSection; -import forge.gui.BoxedProductCardListViewer; -import forge.gui.CardListViewer; import forge.gui.framework.DragCell; import forge.gui.framework.FScreen; import forge.item.*; import forge.itemmanager.ColumnDef; import forge.itemmanager.ItemManagerConfig; -import forge.itemmanager.SItemManagerUtil; import forge.itemmanager.SpellShopManager; import forge.itemmanager.views.ItemTableColumn; import forge.model.FModel; -import forge.properties.ForgePreferences.FPref; import forge.quest.QuestController; -import forge.quest.io.ReadPriceList; +import forge.quest.QuestSpellShop; import forge.screens.deckeditor.views.*; import forge.screens.home.quest.CSubmenuQuestDecks; import forge.toolbox.FLabel; -import forge.toolbox.FOptionPane; import forge.toolbox.FSkin; import forge.util.ItemPool; -import org.apache.commons.lang3.tuple.Pair; - -import javax.swing.*; - import java.text.DecimalFormat; import java.text.NumberFormat; -import java.util.ArrayList; import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -68,16 +51,16 @@ import java.util.Map.Entry; * @version $Id: CEditorQuestCardShop.java 15088 2012-04-07 11:34:05Z Max mtg $ */ public final class CEditorQuestCardShop extends ACEditorBase { - private final JLabel creditsLabel = new FLabel.Builder() + private final FLabel creditsLabel = new FLabel.Builder() .icon(FSkin.getIcon(FSkinProp.ICO_QUEST_COINSTACK)) .fontSize(15).build(); // TODO: move these to the view where they belong - private final JLabel sellPercentageLabel = new FLabel.Builder().text("0") + private final FLabel sellPercentageLabel = new FLabel.Builder().text("0") .fontSize(11) .build(); @SuppressWarnings("serial") - private final JLabel fullCatalogToggle = new FLabel.Builder().text("See full catalog") + private final FLabel fullCatalogToggle = new FLabel.Builder().text("See full catalog") .fontSize(14).hoverable(true).cmdClick(new UiCommand() { @Override public void run() { @@ -86,7 +69,6 @@ public final class CEditorQuestCardShop extends ACEditorBase cardsForSale; @@ -97,11 +79,6 @@ public final class CEditorQuestCardShop extends ACEditorBase mapPrices = this.r.getPriceList(); - private ItemPool decksUsingMyCards; - // remember changed gui elements private String CCTabLabel = new String(); private String CCAddLabel = new String(); @@ -154,136 +131,6 @@ public final class CEditorQuestCardShop extends ACEditorBase countDecksForEachCard() { - final ItemPool result = new ItemPool(InventoryItem.class); - for (final Deck deck : this.questData.getMyDecks()) { - CardPool main = deck.getMain(); - for (final Entry e : main) { - result.add(e.getKey()); - } - if (deck.has(DeckSection.Sideboard)) { - for (final Entry e : deck.get(DeckSection.Sideboard)) { - // only add card if we haven't already encountered it in main - if (!main.contains(e.getKey())) { - result.add(e.getKey()); - } - } - } - } - return result; - } - - private Integer getCardValue(final InventoryItem card) { - String ns = null; - int value = 1337; // previously this was the returned default - boolean foil = false; - int foilMultiplier = 1; - - if (card instanceof PaperCard) { - ns = card.getName() + "|" + ((PaperCard) card).getEdition(); - foil = ((PaperCard) card).isFoil(); - } else { - ns = card.getName(); - } - - if (this.mapPrices.containsKey(ns)) { - value = this.mapPrices.get(ns); - } else if (card instanceof PaperCard) { - switch (((IPaperCard) card).getRarity()) { - case BasicLand: - value = 4; - break; - case Common: - value = 6; - break; - case Uncommon: - value = 40; - break; - case Rare: - value = 120; - break; - case MythicRare: - value = 600; - break; - default: - value = 15; - break; - } - } else if (card instanceof BoosterPack) { - value = 395; - } else if (card instanceof TournamentPack) { - value = 995; - } else if (card instanceof FatPack) { - value = 2365; - } else if (card instanceof BoosterBox) { - value = 8750; - } else if (card instanceof PreconDeck) { - value = QuestController.getPreconDeals((PreconDeck) card).getCost(); - } - - // TODO: make this changeable via a user-definable property? - if (foil) { - switch (((IPaperCard) card).getRarity()) { - case BasicLand: - foilMultiplier = 2; - break; - case Common: - foilMultiplier = 2; - break; - case Uncommon: - foilMultiplier = 2; - break; - case Rare: - foilMultiplier = 3; - break; - case MythicRare: - foilMultiplier = 3; - break; - default: - foilMultiplier = 2; - break; - } - value *= foilMultiplier; - } - - return Integer.valueOf(value); - } - - private final Function, Comparable> fnPriceCompare = new Function, Comparable>() { - @Override - public Comparable apply(final Entry from) { - return CEditorQuestCardShop.this.getCardValue(from.getKey()); - } - }; - private final Function, Object> fnPriceGet = new Function, Object>() { - @Override - public Object apply(final Entry from) { - return CEditorQuestCardShop.this.getCardValue(from.getKey()); - } - }; - private final Function, Object> fnPriceSellGet = new Function, Object>() { - @Override - public Object apply(final Entry from) { - return (int) (CEditorQuestCardShop.this.multiplier * CEditorQuestCardShop.this.getCardValue(from.getKey())); - } - }; - - private final Function, Comparable> fnDeckCompare = new Function, Comparable>() { - @Override - public Comparable apply(final Entry from) { - final Integer iValue = CEditorQuestCardShop.this.decksUsingMyCards.count(from.getKey()); - return iValue == null ? Integer.valueOf(0) : iValue; - } - }; - private final Function, Object> fnDeckGet = new Function, Object>() { - @Override - public Object apply(final Entry from) { - final Integer iValue = CEditorQuestCardShop.this.decksUsingMyCards.count(from.getKey()); - return iValue == null ? "" : iValue.toString(); - } - }; - //=========== Overridden from ACEditorBase @Override @@ -301,122 +148,8 @@ public final class CEditorQuestCardShop extends ACEditorBase itemsToBuy = new ItemPool(InventoryItem.class); - for (Entry itemEntry : items) { - final InventoryItem item = itemEntry.getKey(); - if (item instanceof PaperCard || item instanceof SealedProduct || item instanceof PreconDeck) { - final int qty = itemEntry.getValue(); - itemsToBuy.add(item, qty); - totalCost += qty * this.getCardValue(item); - } - } - if (itemsToBuy.isEmpty()) { return; } - - List itemFlatList = itemsToBuy.toFlatList(); - String suffix = SItemManagerUtil.getItemDisplayString(itemFlatList, 1, true); - String displayList = SItemManagerUtil.buildDisplayList(itemsToBuy); - String title = "Buy " + suffix; - - long creditsShort = totalCost - this.questData.getAssets().getCredits(); - if (creditsShort > 0) { - FOptionPane.showMessageDialog("You need " + creditsShort + " more credits to purchase the following " + suffix.toLowerCase() + ".\n" + displayList, title); - return; - } - - if (!FOptionPane.showConfirmDialog("Pay " + totalCost + " credits to purchase the following " + - suffix.toLowerCase() + "?\n" + displayList, title, "Buy", "Cancel")) { - return; - } - - ItemPool itemsToAdd = new ItemPool(InventoryItem.class); - - for (Entry itemEntry : itemsToBuy) { - final InventoryItem item = itemEntry.getKey(); - - final int qty = itemEntry.getValue(); - final int value = this.getCardValue(item); - - if (item instanceof PaperCard) { - this.questData.getCards().buyCard((PaperCard) item, qty, value); - itemsToAdd.add(item, qty); - } - else if (item instanceof SealedProduct) { - for (int i = 0; i < qty; i++) { - SealedProduct booster = null; - if (item instanceof BoosterPack) { - booster = (BoosterPack) ((BoosterPack) item).clone(); - } - else if (item instanceof TournamentPack) { - booster = (TournamentPack) ((TournamentPack) item).clone(); - } - else if (item instanceof FatPack) { - booster = (FatPack) ((FatPack) item).clone(); - } - else if (item instanceof BoosterBox) { - booster = (BoosterBox) ((BoosterBox) item).clone(); - } - this.questData.getCards().buyPack(booster, value); - final List newCards = booster.getCards(); - - itemsToAdd.addAllFlat(newCards); - - if (booster instanceof BoxedProduct && FModel.getPreferences().getPrefBoolean(FPref.UI_OPEN_PACKS_INDIV)) { - - int totalPacks = ((BoxedProduct) booster).boosterPacksRemaining(); - boolean skipTheRest = false; - final List remainingCards = new ArrayList<>(); - - while (((BoxedProduct) booster).boosterPacksRemaining() > 0 && !skipTheRest) { - final BoxedProductCardListViewer c = new BoxedProductCardListViewer(booster.getName(), "You have found the following cards inside (Booster Pack " + (totalPacks - ((BoxedProduct) booster).boosterPacksRemaining() + 1) + " of " + totalPacks + "):", ((BoxedProduct) booster).getNextBoosterPack()); - c.setVisible(true); - c.dispose(); - skipTheRest = c.skipTheRest(); - } - - if (skipTheRest) { - while (((BoxedProduct) booster).boosterPacksRemaining() > 0) { - remainingCards.addAll(((BoxedProduct) booster).getNextBoosterPack()); - } - } - - remainingCards.addAll(((BoxedProduct) booster).getExtraCards()); - - if (remainingCards.size() > 0) { - final CardListViewer c = new CardListViewer(booster.getName(), "You have found the following cards inside:", remainingCards); - c.setVisible(true); - c.dispose(); - } - - } else { - final CardListViewer c = new CardListViewer(booster.getName(), "You have found the following cards inside:", newCards); - c.setVisible(true); - c.dispose(); - } - - } - } - else if (item instanceof PreconDeck) { - final PreconDeck deck = (PreconDeck) item; - for (int i = 0; i < qty; i++) { - this.questData.getCards().buyPreconDeck(deck, value); - - itemsToAdd.addAll(deck.getDeck().getMain()); - } - - boolean one = (qty == 1); - FOptionPane.showMessageDialog(String.format( - "%s '%s' %s added to your decklist.%n%n%s cards were also added to your pool.", - one ? "Deck" : String.format("%d copies of deck", qty), - deck.getName(), one ? "was" : "were", one ? "Its" : "Their"), - "Thanks for purchasing!", FOptionPane.INFORMATION_ICON); - } - } - - this.getDeckManager().addItems(itemsToAdd); - this.getCatalogManager().removeItems(itemsToBuy); - - this.creditsLabel.setText("Credits: " + this.questData.getAssets().getCredits()); + QuestSpellShop.buy(items, this.getCatalogManager(), this.getDeckManager(), true); + updateCreditsLabel(); } /* (non-Javadoc) @@ -426,40 +159,8 @@ public final class CEditorQuestCardShop extends ACEditorBase> items, boolean toAlternate) { if (showingFullCatalog || toAlternate) { return; } - long totalReceived = 0; - ItemPool itemsToSell = new ItemPool(InventoryItem.class); - for (Entry itemEntry : items) { - final InventoryItem item = itemEntry.getKey(); - if (item instanceof PaperCard) { - final int qty = itemEntry.getValue(); - itemsToSell.add(item, qty); - totalReceived += qty * Math.min((int) (this.multiplier * this.getCardValue(item)), this.questData.getCards().getSellPriceLimit()); - } - } - if (itemsToSell.isEmpty()) { return; } - - List itemFlatList = itemsToSell.toFlatList(); - String suffix = SItemManagerUtil.getItemDisplayString(itemFlatList, 1, true); - String displayList = SItemManagerUtil.buildDisplayList(itemsToSell); - String title = "Sell " + suffix; - - if (!FOptionPane.showConfirmDialog("Sell the following " + suffix.toLowerCase() + " for " + totalReceived + - " credit" + (totalReceived != 1 ? "s" : "") + "?\n" + displayList, title, "Sell", "Cancel")) { - return; - } - - for (Entry itemEntry : itemsToSell) { - final PaperCard card = (PaperCard) itemEntry.getKey(); - final int qty = itemEntry.getValue(); - final int price = Math.min((int) (this.multiplier * this.getCardValue(card)), this.questData.getCards().getSellPriceLimit()); - - this.questData.getCards().sellCard(card, qty, price); - } - - this.getCatalogManager().addItems(itemsToSell); - this.getDeckManager().removeItems(itemsToSell); - - this.creditsLabel.setText("Credits: " + this.questData.getAssets().getCredits()); + QuestSpellShop.sell(items, this.getCatalogManager(), this.getDeckManager(), true); + updateCreditsLabel(); } @Override @@ -476,24 +177,7 @@ public final class CEditorQuestCardShop extends ACEditorBase> cardsToRemove) { - if (showingFullCatalog) { - return; - } - - this.getCatalogManager().addItems(cardsToRemove); - this.getDeckManager().removeItems(cardsToRemove); - - for (Entry item : cardsToRemove) { - if (!(item.getKey() instanceof PaperCard)) { - continue; - } - PaperCard card = (PaperCard)item.getKey(); - final int price = Math.min((int) (this.multiplier * this.getCardValue(card)), - this.questData.getCards().getSellPriceLimit()); - this.questData.getCards().sellCard(card, item.getValue(), price); - } - + private void updateCreditsLabel() { this.creditsLabel.setText("Credits: " + this.questData.getAssets().getCredits()); } @@ -526,11 +210,11 @@ public final class CEditorQuestCardShop extends ACEditorBase colOverridesDeck = new HashMap(); // Add spell shop-specific columns - ItemTableColumn.addColOverride(ItemManagerConfig.SPELL_SHOP, colOverridesCatalog, ColumnDef.PRICE, this.fnPriceCompare, this.fnPriceGet); + ItemTableColumn.addColOverride(ItemManagerConfig.SPELL_SHOP, colOverridesCatalog, ColumnDef.PRICE, QuestSpellShop.fnPriceCompare, QuestSpellShop.fnPriceGet); ItemTableColumn.addColOverride(ItemManagerConfig.SPELL_SHOP, colOverridesCatalog, ColumnDef.OWNED, questData.getCards().getFnOwnedCompare(), questData.getCards().getFnOwnedGet()); - ItemTableColumn.addColOverride(ItemManagerConfig.QUEST_INVENTORY, colOverridesDeck, ColumnDef.PRICE, this.fnPriceCompare, this.fnPriceSellGet); + ItemTableColumn.addColOverride(ItemManagerConfig.QUEST_INVENTORY, colOverridesDeck, ColumnDef.PRICE, QuestSpellShop.fnPriceCompare, QuestSpellShop.fnPriceSellGet); ItemTableColumn.addColOverride(ItemManagerConfig.QUEST_INVENTORY, colOverridesDeck, ColumnDef.NEW, this.questData.getCards().getFnNewCompare(), this.questData.getCards().getFnNewGet()); - ItemTableColumn.addColOverride(ItemManagerConfig.QUEST_INVENTORY, colOverridesDeck, ColumnDef.DECKS, this.fnDeckCompare, this.fnDeckGet); + ItemTableColumn.addColOverride(ItemManagerConfig.QUEST_INVENTORY, colOverridesDeck, ColumnDef.DECKS, QuestSpellShop.fnDeckCompare, QuestSpellShop.fnDeckGet); // Setup with current column set this.getCatalogManager().setup(ItemManagerConfig.SPELL_SHOP, colOverridesCatalog); @@ -558,8 +242,8 @@ public final class CEditorQuestCardShop extends ACEditorBase ownedItems = new ItemPool(InventoryItem.class); @@ -573,25 +257,15 @@ public final class CEditorQuestCardShop extends ACEditorBase> cardsToRemove = new LinkedList>(); - for (Entry item : getDeckManager().getPool()) { - PaperCard card = (PaperCard)item.getKey(); - int numToKeep = card.getRules().getType().isBasic() ? 50 : 4; - if ("Relentless Rats".equals(card.getName())) { - numToKeep = Integer.MAX_VALUE; - } - if (numToKeep < item.getValue()) { - cardsToRemove.add(Pair.of(item.getKey(), item.getValue() - numToKeep)); - } - } - removeCards(cardsToRemove); + QuestSpellShop.sellExtras(getCatalogManager(), getDeckManager()); + updateCreditsLabel(); } }); this.getDeckManager().getPnlButtons().add(creditsLabel, "gap 5px"); - this.creditsLabel.setText("Credits: " + this.questData.getAssets().getCredits()); + updateCreditsLabel(); - final double multiPercent = this.multiplier * 100; + final double multiPercent = multiplier * 100; final NumberFormat formatter = new DecimalFormat("#0.00"); String maxSellingPrice = ""; final int maxSellPrice = this.questData.getCards().getSellPriceLimit(); diff --git a/forge-gui-mobile/src/forge/GuiMobile.java b/forge-gui-mobile/src/forge/GuiMobile.java index db1940e71d7..764b9a7f003 100644 --- a/forge-gui-mobile/src/forge/GuiMobile.java +++ b/forge-gui-mobile/src/forge/GuiMobile.java @@ -174,6 +174,14 @@ public class GuiMobile implements IGuiBase { FDeckViewer.show(deck); } + @Override + public boolean showBoxedProduct(final String title, final String message, final List list) { + Deck deck = new Deck(title + " - " + message); //TODO: Make this nicer + deck.getMain().addAllFlat(list); + FDeckViewer.show(deck); + return false; + } + @Override public IButton getBtnOK() { return FControl.getView().getPrompt().getBtnOk(); diff --git a/forge-gui-mobile/src/forge/screens/TabPageScreen.java b/forge-gui-mobile/src/forge/screens/TabPageScreen.java index b744b7dfef1..943e393b930 100644 --- a/forge-gui-mobile/src/forge/screens/TabPageScreen.java +++ b/forge-gui-mobile/src/forge/screens/TabPageScreen.java @@ -20,7 +20,7 @@ public class TabPageScreen> extends FScreen { private TabPage selectedPage; @SuppressWarnings("unchecked") - public TabPageScreen(TabPage[] tabPages0) { + public TabPageScreen(TabPage... tabPages0) { super(new TabHeader(tabPages0)); int index = 0; diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestDeckEditor.java b/forge-gui-mobile/src/forge/screens/quest/QuestDeckEditor.java index 3f8d24495ab..7949fe81940 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestDeckEditor.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestDeckEditor.java @@ -2,23 +2,16 @@ package forge.screens.quest; import java.util.HashMap; import java.util.Map; -import java.util.Map.Entry; - -import com.google.common.base.Function; - -import forge.deck.Deck; import forge.deck.DeckProxy; import forge.deck.FDeckEditor; -import forge.item.InventoryItem; import forge.item.PaperCard; import forge.itemmanager.ColumnDef; import forge.itemmanager.ItemColumn; import forge.itemmanager.ItemManagerConfig; import forge.model.FModel; +import forge.quest.QuestSpellShop; public class QuestDeckEditor extends FDeckEditor { - private Map decksUsingMyCards; - public QuestDeckEditor() { super(EditorType.Quest, "", false); } @@ -29,7 +22,7 @@ public class QuestDeckEditor extends FDeckEditor { @Override public void onActivate() { super.onActivate(); - decksUsingMyCards = countDecksForEachCard(); + QuestSpellShop.updateDecksForEachCard(); } @Override @@ -41,21 +34,7 @@ public class QuestDeckEditor extends FDeckEditor { break; case QUEST_DECK_EDITOR: ItemColumn.addColOverride(config, colOverrides, ColumnDef.NEW, FModel.getQuest().getCards().getFnNewCompare(), FModel.getQuest().getCards().getFnNewGet()); - ItemColumn.addColOverride(config, colOverrides, ColumnDef.DECKS, - new Function, Comparable>() { - @Override - public Comparable apply(final Entry from) { - final Integer iValue = decksUsingMyCards.get(from.getKey()); - return iValue == null ? Integer.valueOf(0) : iValue; - } - }, - new Function, Object>() { - @Override - public Object apply(final Entry from) { - final Integer iValue = decksUsingMyCards.get(from.getKey()); - return iValue == null ? "" : iValue.toString(); - } - }); + ItemColumn.addColOverride(config, colOverrides, ColumnDef.DECKS, QuestSpellShop.fnDeckCompare, QuestSpellShop.fnDeckGet); break; default: colOverrides = null; //shouldn't happen @@ -73,17 +52,4 @@ public class QuestDeckEditor extends FDeckEditor { getCatalogPage().addCard(card, qty); FModel.getQuest().getCards().getCardpool().add(card, qty); } - - // fills number of decks using each card - private Map countDecksForEachCard() { - final Map result = new HashMap(); - for (final Deck deck : FModel.getQuest().getMyDecks()) { - for (final Entry e : deck.getMain()) { - final PaperCard card = e.getKey(); - final Integer amount = result.get(card); - result.put(card, Integer.valueOf(amount == null ? 1 : 1 + amount.intValue())); - } - } - return result; - } } diff --git a/forge-gui-mobile/src/forge/screens/quest/QuestSpellShopScreen.java b/forge-gui-mobile/src/forge/screens/quest/QuestSpellShopScreen.java index 5a63bcb6fb7..4927ae70d5f 100644 --- a/forge-gui-mobile/src/forge/screens/quest/QuestSpellShopScreen.java +++ b/forge-gui-mobile/src/forge/screens/quest/QuestSpellShopScreen.java @@ -1,15 +1,123 @@ package forge.screens.quest; -import forge.screens.FScreen; +import java.util.HashMap; +import java.util.Map; -public class QuestSpellShopScreen extends FScreen { +import forge.assets.FSkinImage; +import forge.card.CardZoom; +import forge.item.InventoryItem; +import forge.item.PaperCard; +import forge.itemmanager.ColumnDef; +import forge.itemmanager.ItemColumn; +import forge.itemmanager.ItemManagerConfig; +import forge.itemmanager.SpellShopManager; +import forge.itemmanager.ItemManager.ContextMenuBuilder; +import forge.menu.FDropDownMenu; +import forge.menu.FMenuItem; +import forge.model.FModel; +import forge.quest.QuestSpellShop; +import forge.screens.TabPageScreen; +import forge.toolbox.FEvent; +import forge.toolbox.FEvent.FEventHandler; +import forge.util.ItemPool; + +public class QuestSpellShopScreen extends TabPageScreen { + @SuppressWarnings("unchecked") public QuestSpellShopScreen() { - super("Spell Shop", QuestMenu.getMenu()); + super(new SpellShopPage(), new InventoryPage()); } @Override - protected void doLayout(float startY, float width, float height) { - // TODO Auto-generated method stub - + public void onActivate() { + super.onActivate(); + update(); + } + + public void update() { + QuestSpellShop.updateDecksForEachCard(); + QuestSpellShop.updateMultiplier(); + ((SpellShopPage)tabPages[0]).refresh(); + ((InventoryPage)tabPages[1]).refresh(); + } + + private static class SpellShopPage extends TabPage { + private final SpellShopManager shopManager = add(new SpellShopManager(false)); + + private SpellShopPage() { + super("Spell Shop", FSkinImage.QUEST_BOOK); + shopManager.setItemActivateHandler(new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + } + }); + shopManager.setContextMenuBuilder(new ContextMenuBuilder() { + @Override + public void buildMenu(final FDropDownMenu menu, final InventoryItem item) { + if (item instanceof PaperCard) { + menu.addItem(new FMenuItem("Zoom/Details", new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + CardZoom.show((PaperCard)item); + } + })); + } + } + }); + Map colOverrides = new HashMap(); + ItemColumn.addColOverride(ItemManagerConfig.SPELL_SHOP, colOverrides, ColumnDef.PRICE, QuestSpellShop.fnPriceCompare, QuestSpellShop.fnPriceGet); + ItemColumn.addColOverride(ItemManagerConfig.SPELL_SHOP, colOverrides, ColumnDef.OWNED, FModel.getQuest().getCards().getFnOwnedCompare(), FModel.getQuest().getCards().getFnOwnedGet()); + shopManager.setup(ItemManagerConfig.SPELL_SHOP, colOverrides); + } + + public void refresh() { + shopManager.setPool(FModel.getQuest().getCards().getShopList()); + } + + @Override + protected void doLayout(float width, float height) { + shopManager.setBounds(0, 0, width, height); + } + } + + private static class InventoryPage extends TabPage { + private final SpellShopManager inventoryManager = add(new SpellShopManager(false)); + + private InventoryPage() { + super("Inventory", FSkinImage.QUEST_BOX); + inventoryManager.setItemActivateHandler(new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + } + }); + inventoryManager.setContextMenuBuilder(new ContextMenuBuilder() { + @Override + public void buildMenu(final FDropDownMenu menu, final InventoryItem item) { + if (item instanceof PaperCard) { + menu.addItem(new FMenuItem("Zoom/Details", new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + CardZoom.show((PaperCard)item); + } + })); + } + } + }); + Map colOverrides = new HashMap(); + ItemColumn.addColOverride(ItemManagerConfig.QUEST_INVENTORY, colOverrides, ColumnDef.PRICE, QuestSpellShop.fnPriceCompare, QuestSpellShop.fnPriceSellGet); + ItemColumn.addColOverride(ItemManagerConfig.QUEST_INVENTORY, colOverrides, ColumnDef.NEW, FModel.getQuest().getCards().getFnNewCompare(), FModel.getQuest().getCards().getFnNewGet()); + ItemColumn.addColOverride(ItemManagerConfig.QUEST_INVENTORY, colOverrides, ColumnDef.DECKS, QuestSpellShop.fnDeckCompare, QuestSpellShop.fnDeckGet); + inventoryManager.setup(ItemManagerConfig.QUEST_INVENTORY, colOverrides); + } + + public void refresh() { + final ItemPool ownedItems = new ItemPool(InventoryItem.class); + ownedItems.addAll(FModel.getQuest().getCards().getCardpool().getView()); + inventoryManager.setPool(ownedItems); + } + + @Override + protected void doLayout(float width, float height) { + inventoryManager.setBounds(0, 0, width, height); + } } } diff --git a/forge-gui/src/main/java/forge/interfaces/IGuiBase.java b/forge-gui/src/main/java/forge/interfaces/IGuiBase.java index 2a7ea99b2cd..56c44a27c27 100644 --- a/forge-gui/src/main/java/forge/interfaces/IGuiBase.java +++ b/forge-gui/src/main/java/forge/interfaces/IGuiBase.java @@ -53,6 +53,7 @@ public interface IGuiBase { String showFileDialog(String title, String defaultDir); File getSaveFile(File defaultFile); void showCardList(final String title, final String message, final List list); + boolean showBoxedProduct(final String title, final String message, final List list); void fireEvent(UiEvent e); void setCard(Card card); void showCombat(Combat combat); diff --git a/forge-gui/src/main/java/forge/quest/QuestController.java b/forge-gui/src/main/java/forge/quest/QuestController.java index e9c63102c0b..02b53c8af03 100644 --- a/forge-gui/src/main/java/forge/quest/QuestController.java +++ b/forge-gui/src/main/java/forge/quest/QuestController.java @@ -24,7 +24,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; - import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.eventbus.Subscribe; diff --git a/forge-gui/src/main/java/forge/quest/QuestSpellShop.java b/forge-gui/src/main/java/forge/quest/QuestSpellShop.java new file mode 100644 index 00000000000..2ff65490930 --- /dev/null +++ b/forge-gui/src/main/java/forge/quest/QuestSpellShop.java @@ -0,0 +1,347 @@ +package forge.quest; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.base.Function; + +import forge.GuiBase; +import forge.deck.CardPool; +import forge.deck.Deck; +import forge.deck.DeckSection; +import forge.item.BoosterBox; +import forge.item.BoosterPack; +import forge.item.BoxedProduct; +import forge.item.FatPack; +import forge.item.IPaperCard; +import forge.item.InventoryItem; +import forge.item.PaperCard; +import forge.item.PreconDeck; +import forge.item.SealedProduct; +import forge.item.TournamentPack; +import forge.itemmanager.IItemManager; +import forge.itemmanager.SItemManagerUtil; +import forge.model.FModel; +import forge.properties.ForgePreferences.FPref; +import forge.quest.io.ReadPriceList; +import forge.util.ItemPool; +import forge.util.gui.SOptionPane; + +public class QuestSpellShop { + private static final ReadPriceList r = new ReadPriceList(); + private static final Map mapPrices = r.getPriceList(); + private static double multiplier; + private static ItemPool decksUsingMyCards; + + public static Integer getCardValue(final InventoryItem card) { + String ns = null; + int value = 1337; // previously this was the returned default + boolean foil = false; + int foilMultiplier = 1; + + if (card instanceof PaperCard) { + ns = card.getName() + "|" + ((PaperCard) card).getEdition(); + foil = ((PaperCard) card).isFoil(); + } else { + ns = card.getName(); + } + + if (mapPrices.containsKey(ns)) { + value = mapPrices.get(ns); + } else if (card instanceof PaperCard) { + switch (((IPaperCard) card).getRarity()) { + case BasicLand: + value = 4; + break; + case Common: + value = 6; + break; + case Uncommon: + value = 40; + break; + case Rare: + value = 120; + break; + case MythicRare: + value = 600; + break; + default: + value = 15; + break; + } + } else if (card instanceof BoosterPack) { + value = 395; + } else if (card instanceof TournamentPack) { + value = 995; + } else if (card instanceof FatPack) { + value = 2365; + } else if (card instanceof BoosterBox) { + value = 8750; + } else if (card instanceof PreconDeck) { + value = QuestController.getPreconDeals((PreconDeck) card).getCost(); + } + + // TODO: make this changeable via a user-definable property? + if (foil) { + switch (((IPaperCard) card).getRarity()) { + case BasicLand: + foilMultiplier = 2; + break; + case Common: + foilMultiplier = 2; + break; + case Uncommon: + foilMultiplier = 2; + break; + case Rare: + foilMultiplier = 3; + break; + case MythicRare: + foilMultiplier = 3; + break; + default: + foilMultiplier = 2; + break; + } + value *= foilMultiplier; + } + + return Integer.valueOf(value); + } + + public static final Function, Comparable> fnPriceCompare = new Function, Comparable>() { + @Override + public Comparable apply(final Entry from) { + return getCardValue(from.getKey()); + } + }; + public static final Function, Object> fnPriceGet = new Function, Object>() { + @Override + public Object apply(final Entry from) { + return getCardValue(from.getKey()); + } + }; + public static final Function, Object> fnPriceSellGet = new Function, Object>() { + @Override + public Object apply(final Entry from) { + return (int) (multiplier * getCardValue(from.getKey())); + } + }; + public static final Function, Comparable> fnDeckCompare = new Function, Comparable>() { + @Override + public Comparable apply(final Entry from) { + final Integer iValue = decksUsingMyCards.count(from.getKey()); + return iValue == null ? Integer.valueOf(0) : iValue; + } + }; + public static final Function, Object> fnDeckGet = new Function, Object>() { + @Override + public Object apply(final Entry from) { + final Integer iValue = decksUsingMyCards.count(from.getKey()); + return iValue == null ? "" : iValue.toString(); + } + }; + + public static void buy(Iterable> items, IItemManager shopManager, IItemManager inventoryManager, boolean confirmPurchase) { + long totalCost = 0; + ItemPool itemsToBuy = new ItemPool(InventoryItem.class); + for (Entry itemEntry : items) { + final InventoryItem item = itemEntry.getKey(); + if (item instanceof PaperCard || item instanceof SealedProduct || item instanceof PreconDeck) { + final int qty = itemEntry.getValue(); + itemsToBuy.add(item, qty); + totalCost += qty * QuestSpellShop.getCardValue(item); + } + } + if (itemsToBuy.isEmpty()) { return; } + + List itemFlatList = itemsToBuy.toFlatList(); + String suffix = SItemManagerUtil.getItemDisplayString(itemFlatList, 1, true); + String displayList = SItemManagerUtil.buildDisplayList(itemsToBuy); + String title = "Buy " + suffix; + + long creditsShort = totalCost - FModel.getQuest().getAssets().getCredits(); + if (creditsShort > 0) { + SOptionPane.showMessageDialog("You need " + creditsShort + " more credits to purchase the following " + suffix.toLowerCase() + ".\n" + displayList, title); + return; + } + + if (confirmPurchase && !SOptionPane.showConfirmDialog("Pay " + totalCost + " credits to purchase the following " + + suffix.toLowerCase() + "?\n" + displayList, title, "Buy", "Cancel")) { + return; + } + + ItemPool itemsToAdd = new ItemPool(InventoryItem.class); + + for (Entry itemEntry : itemsToBuy) { + final InventoryItem item = itemEntry.getKey(); + + final int qty = itemEntry.getValue(); + final int value = QuestSpellShop.getCardValue(item); + + if (item instanceof PaperCard) { + FModel.getQuest().getCards().buyCard((PaperCard) item, qty, value); + itemsToAdd.add(item, qty); + } + else if (item instanceof SealedProduct) { + for (int i = 0; i < qty; i++) { + SealedProduct booster = null; + if (item instanceof BoosterPack) { + booster = (BoosterPack) ((BoosterPack) item).clone(); + } + else if (item instanceof TournamentPack) { + booster = (TournamentPack) ((TournamentPack) item).clone(); + } + else if (item instanceof FatPack) { + booster = (FatPack) ((FatPack) item).clone(); + } + else if (item instanceof BoosterBox) { + booster = (BoosterBox) ((BoosterBox) item).clone(); + } + FModel.getQuest().getCards().buyPack(booster, value); + final List newCards = booster.getCards(); + + itemsToAdd.addAllFlat(newCards); + + if (booster instanceof BoxedProduct && FModel.getPreferences().getPrefBoolean(FPref.UI_OPEN_PACKS_INDIV)) { + + int totalPacks = ((BoxedProduct) booster).boosterPacksRemaining(); + boolean skipTheRest = false; + final List remainingCards = new ArrayList<>(); + + while (((BoxedProduct) booster).boosterPacksRemaining() > 0 && !skipTheRest) { + skipTheRest = GuiBase.getInterface().showBoxedProduct(booster.getName(), "You have found the following cards inside (Booster Pack " + (totalPacks - ((BoxedProduct) booster).boosterPacksRemaining() + 1) + " of " + totalPacks + "):", ((BoxedProduct) booster).getNextBoosterPack()); + } + + if (skipTheRest) { + while (((BoxedProduct) booster).boosterPacksRemaining() > 0) { + remainingCards.addAll(((BoxedProduct) booster).getNextBoosterPack()); + } + } + + remainingCards.addAll(((BoxedProduct) booster).getExtraCards()); + + if (remainingCards.size() > 0) { + GuiBase.getInterface().showCardList(booster.getName(), "You have found the following cards inside:", remainingCards); + } + + } + else { + GuiBase.getInterface().showCardList(booster.getName(), "You have found the following cards inside:", newCards); + } + } + } + else if (item instanceof PreconDeck) { + final PreconDeck deck = (PreconDeck) item; + for (int i = 0; i < qty; i++) { + FModel.getQuest().getCards().buyPreconDeck(deck, value); + + itemsToAdd.addAll(deck.getDeck().getMain()); + } + + boolean one = (qty == 1); + SOptionPane.showMessageDialog(String.format( + "%s '%s' %s added to your decklist.%n%n%s cards were also added to your pool.", + one ? "Deck" : String.format("%d copies of deck", qty), + deck.getName(), one ? "was" : "were", one ? "Its" : "Their"), + "Thanks for purchasing!", SOptionPane.INFORMATION_ICON); + } + } + + inventoryManager.addItems(itemsToAdd); + shopManager.removeItems(itemsToBuy); + } + + public static void sell(Iterable> items, IItemManager shopManager, IItemManager inventoryManager, boolean confirmSale) { + long totalReceived = 0; + ItemPool itemsToSell = new ItemPool(InventoryItem.class); + for (Entry itemEntry : items) { + final InventoryItem item = itemEntry.getKey(); + if (item instanceof PaperCard) { + final int qty = itemEntry.getValue(); + itemsToSell.add(item, qty); + totalReceived += qty * Math.min((int) (multiplier * getCardValue(item)), FModel.getQuest().getCards().getSellPriceLimit()); + } + } + if (itemsToSell.isEmpty()) { return; } + + if (confirmSale) { + List itemFlatList = itemsToSell.toFlatList(); + String suffix = SItemManagerUtil.getItemDisplayString(itemFlatList, 1, true); + String displayList = SItemManagerUtil.buildDisplayList(itemsToSell); + String title = "Sell " + suffix; + + if (!SOptionPane.showConfirmDialog("Sell the following " + suffix.toLowerCase() + " for " + totalReceived + + " credit" + (totalReceived != 1 ? "s" : "") + "?\n" + displayList, title, "Sell", "Cancel")) { + return; + } + } + + for (Entry itemEntry : itemsToSell) { + final PaperCard card = (PaperCard) itemEntry.getKey(); + final int qty = itemEntry.getValue(); + final int price = Math.min((int) (multiplier * getCardValue(card)), FModel.getQuest().getCards().getSellPriceLimit()); + + FModel.getQuest().getCards().sellCard(card, qty, price); + } + + shopManager.addItems(itemsToSell); + inventoryManager.removeItems(itemsToSell); + } + + public static void sellExtras(IItemManager shopManager, IItemManager inventoryManager) { + List> cardsToRemove = new LinkedList>(); + for (Entry item : inventoryManager.getPool()) { + PaperCard card = (PaperCard)item.getKey(); + int numToKeep = card.getRules().getType().isBasic() ? 50 : 4; + if ("Relentless Rats".equals(card.getName())) { + numToKeep = Integer.MAX_VALUE; + } + if (numToKeep < item.getValue()) { + cardsToRemove.add(Pair.of(item.getKey(), item.getValue() - numToKeep)); + } + } + + shopManager.addItems(cardsToRemove); + inventoryManager.removeItems(cardsToRemove); + + for (Entry item : cardsToRemove) { + if (!(item.getKey() instanceof PaperCard)) { + continue; + } + PaperCard card = (PaperCard)item.getKey(); + final int price = Math.min((int) (multiplier * getCardValue(card)), + FModel.getQuest().getCards().getSellPriceLimit()); + FModel.getQuest().getCards().sellCard(card, item.getValue(), price); + } + } + + // fills number of decks using each card + public static void updateDecksForEachCard() { + decksUsingMyCards = new ItemPool(InventoryItem.class); + for (final Deck deck : FModel.getQuest().getMyDecks()) { + CardPool main = deck.getMain(); + for (final Entry e : main) { + decksUsingMyCards.add(e.getKey()); + } + if (deck.has(DeckSection.Sideboard)) { + for (final Entry e : deck.get(DeckSection.Sideboard)) { + // only add card if we haven't already encountered it in main + if (!main.contains(e.getKey())) { + decksUsingMyCards.add(e.getKey()); + } + } + } + } + } + + public static double updateMultiplier() { + multiplier = FModel.getQuest().getCards().getSellMultiplier(); + return multiplier; + } +}