mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Add quest classes to mobile game
This commit is contained in:
49
.gitattributes
vendored
49
.gitattributes
vendored
@@ -16224,6 +16224,54 @@ forge-m-base/src/forge/player/HumanPlaySpellAbility.java -text
|
||||
forge-m-base/src/forge/player/LobbyPlayerHuman.java -text
|
||||
forge-m-base/src/forge/player/PlayerControllerHuman.java -text
|
||||
forge-m-base/src/forge/player/TargetSelection.java -text
|
||||
forge-m-base/src/forge/quest/BoosterUtils.java -text
|
||||
forge-m-base/src/forge/quest/IQuestRewardCard.java -text
|
||||
forge-m-base/src/forge/quest/QuestController.java -text
|
||||
forge-m-base/src/forge/quest/QuestDeckMap.java -text
|
||||
forge-m-base/src/forge/quest/QuestEvent.java -text
|
||||
forge-m-base/src/forge/quest/QuestEventChallenge.java -text
|
||||
forge-m-base/src/forge/quest/QuestEventDifficulty.java -text
|
||||
forge-m-base/src/forge/quest/QuestEventDuel.java -text
|
||||
forge-m-base/src/forge/quest/QuestEventDuelManager.java -text
|
||||
forge-m-base/src/forge/quest/QuestMode.java -text
|
||||
forge-m-base/src/forge/quest/QuestRewardCard.java -text
|
||||
forge-m-base/src/forge/quest/QuestRewardCardChooser.java -text
|
||||
forge-m-base/src/forge/quest/QuestRewardCardDuplicate.java -text
|
||||
forge-m-base/src/forge/quest/QuestRewardCardFiltered.java -text
|
||||
forge-m-base/src/forge/quest/QuestUtil.java -text
|
||||
forge-m-base/src/forge/quest/QuestUtilCards.java -text
|
||||
forge-m-base/src/forge/quest/QuestUtilUnlockSets.java -text
|
||||
forge-m-base/src/forge/quest/QuestWorld.java -text
|
||||
forge-m-base/src/forge/quest/SellRules.java -text
|
||||
forge-m-base/src/forge/quest/StartingPoolPreferences.java -text
|
||||
forge-m-base/src/forge/quest/StartingPoolType.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/IQuestBazaarItem.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestBazaarManager.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestItemBasic.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestItemCharmOfVigor.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestItemElixir.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestItemEstates.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestItemPoundFlesh.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestItemType.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestItemZeppelin.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestPetController.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestPetStats.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestPetStorage.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/QuestStallDefinition.java -text
|
||||
forge-m-base/src/forge/quest/bazaar/package-info.java -text
|
||||
forge-m-base/src/forge/quest/data/GameFormatQuest.java -text
|
||||
forge-m-base/src/forge/quest/data/QuestAchievements.java -text
|
||||
forge-m-base/src/forge/quest/data/QuestAssets.java -text
|
||||
forge-m-base/src/forge/quest/data/QuestData.java -text
|
||||
forge-m-base/src/forge/quest/data/QuestItemCondition.java -text
|
||||
forge-m-base/src/forge/quest/data/QuestPreferences.java -text
|
||||
forge-m-base/src/forge/quest/data/package-info.java -text
|
||||
forge-m-base/src/forge/quest/io/QuestChallengeReader.java -text
|
||||
forge-m-base/src/forge/quest/io/QuestDataIO.java -text
|
||||
forge-m-base/src/forge/quest/io/QuestDuelReader.java -text
|
||||
forge-m-base/src/forge/quest/io/ReadPriceList.java -text
|
||||
forge-m-base/src/forge/quest/io/package-info.java -text
|
||||
forge-m-base/src/forge/quest/package-info.java -text
|
||||
forge-m-base/src/forge/screens/FScreen.java -text
|
||||
forge-m-base/src/forge/screens/LaunchScreen.java -text
|
||||
forge-m-base/src/forge/screens/SplashScreen.java -text
|
||||
@@ -16322,6 +16370,7 @@ forge-m-base/src/forge/utils/PhysicsObject.java -text
|
||||
forge-m-base/src/forge/utils/Preferences.java -text
|
||||
forge-m-base/src/forge/utils/PreferencesStore.java -text
|
||||
forge-m-base/src/forge/utils/Utils.java -text
|
||||
forge-m-base/src/forge/utils/XmlUtil.java -text
|
||||
forge-m-desktop/.classpath -text
|
||||
forge-m-desktop/.project -text
|
||||
forge-m-desktop/.settings/org.eclipse.jdt.core.prefs -text
|
||||
|
||||
@@ -19,6 +19,8 @@ import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.PreconDeck;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.QuestController;
|
||||
import forge.quest.QuestEvent;
|
||||
import forge.util.IHasName;
|
||||
import forge.util.storage.IStorage;
|
||||
import forge.util.storage.StorageImmediatelySerialized;
|
||||
@@ -324,7 +326,7 @@ public class DeckProxy implements InventoryItem {
|
||||
return decks;
|
||||
}
|
||||
|
||||
/* public static Iterable<DeckProxy> getAllQuestEventAndChallenges() {
|
||||
public static Iterable<DeckProxy> getAllQuestEventAndChallenges() {
|
||||
ArrayList<DeckProxy> decks = new ArrayList<DeckProxy>();
|
||||
QuestController quest = FModel.getQuest();
|
||||
for (QuestEvent e : quest.getDuelsManager().getAllDuels()) {
|
||||
@@ -334,7 +336,7 @@ public class DeckProxy implements InventoryItem {
|
||||
decks.add(new DeckProxy(e.getEventDeck(), "Quest Event", null, null));
|
||||
}
|
||||
return decks;
|
||||
}*/
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Iterable<DeckProxy> getAllSealedDecks(IStorage<DeckGroup> sealed) {
|
||||
|
||||
@@ -15,6 +15,10 @@ import forge.deck.generation.*;
|
||||
import forge.item.PaperCard;
|
||||
import forge.itemmanager.DeckManager;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.QuestController;
|
||||
import forge.quest.QuestEvent;
|
||||
import forge.quest.QuestEventChallenge;
|
||||
import forge.quest.QuestEventDuel;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.Lang;
|
||||
@@ -82,7 +86,7 @@ public class DeckgenUtil {
|
||||
return deck;
|
||||
}
|
||||
|
||||
/*public static QuestEvent getQuestEvent(final String name) {
|
||||
public static QuestEvent getQuestEvent(final String name) {
|
||||
QuestController qCtrl = FModel.getQuest();
|
||||
for (QuestEventChallenge challenge : qCtrl.getChallenges()) {
|
||||
if (challenge.getTitle().equals(name)) {
|
||||
@@ -94,7 +98,7 @@ public class DeckgenUtil {
|
||||
@Override public boolean apply(QuestEventDuel in) { return in.getName().equals(name); }
|
||||
});
|
||||
return duel;
|
||||
}*/
|
||||
}
|
||||
|
||||
/** @return {@link forge.deck.Deck} */
|
||||
public static Deck getRandomColorDeck(boolean forAi) {
|
||||
@@ -116,7 +120,7 @@ public class DeckgenUtil {
|
||||
return allDecks.get(name);
|
||||
}
|
||||
|
||||
/*public static Deck getRandomQuestDeck() {
|
||||
public static Deck getRandomQuestDeck() {
|
||||
final List<Deck> allQuestDecks = new ArrayList<Deck>();
|
||||
QuestController qCtrl = FModel.getQuest();
|
||||
|
||||
@@ -130,7 +134,7 @@ public class DeckgenUtil {
|
||||
|
||||
final int rand = (int) (Math.floor(Math.random() * allQuestDecks.size()));
|
||||
return allQuestDecks.get(rand);
|
||||
}*/
|
||||
}
|
||||
|
||||
public static void randomSelectColors(final DeckManager deckManager) {
|
||||
final int size = deckManager.getItemCount();
|
||||
|
||||
@@ -6,6 +6,10 @@ import forge.game.player.RegisteredPlayer;
|
||||
import forge.itemmanager.DeckManager;
|
||||
import forge.itemmanager.ItemManagerConfig;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.QuestController;
|
||||
import forge.quest.QuestEvent;
|
||||
import forge.quest.QuestEventChallenge;
|
||||
import forge.quest.QuestUtil;
|
||||
import forge.screens.FScreen;
|
||||
import forge.toolbox.FComboBox;
|
||||
import forge.toolbox.FEvent;
|
||||
@@ -57,6 +61,25 @@ public class FDeckChooser extends FScreen {
|
||||
public void initialize(FPref savedStateSetting, DeckType defaultDeckType) {
|
||||
stateSetting = savedStateSetting;
|
||||
selectedDeckType = defaultDeckType;
|
||||
|
||||
if (decksComboBox == null) { //initialize components with delayed initialization the first time this is populated
|
||||
decksComboBox = new FComboBox<DeckType>();
|
||||
restoreSavedState();
|
||||
decksComboBox.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
refreshDecksList(decksComboBox.getSelectedItem(), false, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
clear();
|
||||
restoreSavedState(); //ensure decks refreshed and state restored in case any deleted or added since last loaded
|
||||
}
|
||||
add(decksComboBox);
|
||||
add(lstDecks);
|
||||
add(btnViewDeck);
|
||||
add(btnRandom);
|
||||
}
|
||||
|
||||
public DeckType getSelectedDeckType() { return selectedDeckType; }
|
||||
@@ -125,7 +148,6 @@ public class FDeckChooser extends FScreen {
|
||||
public boolean isGeneratedDeck() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void updateColors() {
|
||||
@@ -173,7 +195,7 @@ public class FDeckChooser extends FScreen {
|
||||
private void updatePrecons() {
|
||||
lstDecks.setAllowMultipleSelections(false);
|
||||
|
||||
//lstDecks.setPool(DeckProxy.getAllPreconstructedDecks(QuestController.getPrecons()));
|
||||
lstDecks.setPool(DeckProxy.getAllPreconstructedDecks(QuestController.getPrecons()));
|
||||
lstDecks.setup(ItemManagerConfig.PRECON_DECKS);
|
||||
|
||||
btnRandom.setText("Random Deck");
|
||||
@@ -190,7 +212,7 @@ public class FDeckChooser extends FScreen {
|
||||
private void updateQuestEvents() {
|
||||
lstDecks.setAllowMultipleSelections(false);
|
||||
|
||||
//lstDecks.setPool(DeckProxy.getAllQuestEventAndChallenges());
|
||||
lstDecks.setPool(DeckProxy.getAllQuestEventAndChallenges());
|
||||
lstDecks.setup(ItemManagerConfig.QUEST_EVENT_DECKS);
|
||||
|
||||
btnRandom.setText("Random Deck");
|
||||
@@ -215,39 +237,18 @@ public class FDeckChooser extends FScreen {
|
||||
|
||||
// Special branch for quest events
|
||||
if (selectedDeckType == DeckType.QUEST_OPPONENT_DECK) {
|
||||
/*QuestEvent event = DeckgenUtil.getQuestEvent(lstDecks.getSelectedItem().getName());
|
||||
QuestEvent event = DeckgenUtil.getQuestEvent(lstDecks.getSelectedItem().getName());
|
||||
RegisteredPlayer result = new RegisteredPlayer(event.getEventDeck());
|
||||
if (event instanceof QuestEventChallenge) {
|
||||
result.setStartingLife(((QuestEventChallenge) event).getAiLife());
|
||||
}
|
||||
result.setCardsOnBattlefield(QuestUtil.getComputerStartingCards(event));
|
||||
return result;*/
|
||||
return result;
|
||||
}
|
||||
|
||||
return new RegisteredPlayer(getDeck());
|
||||
}
|
||||
|
||||
public void populate() {
|
||||
if (decksComboBox == null) { //initialize components with delayed initialization the first time this is populated
|
||||
decksComboBox = new FComboBox<DeckType>();
|
||||
restoreSavedState();
|
||||
decksComboBox.setChangedHandler(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
refreshDecksList(decksComboBox.getSelectedItem(), false, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
clear();
|
||||
restoreSavedState(); //ensure decks refreshed and state restored in case any deleted or added since last loaded
|
||||
}
|
||||
add(decksComboBox);
|
||||
add(lstDecks);
|
||||
add(btnViewDeck);
|
||||
add(btnRandom);
|
||||
}
|
||||
|
||||
public final boolean isAi() {
|
||||
return isAi;
|
||||
}
|
||||
@@ -263,6 +264,8 @@ public class FDeckChooser extends FScreen {
|
||||
if (e == null) {
|
||||
decksComboBox.setSelectedItem(deckType);
|
||||
}
|
||||
if (deckType == null) { return; }
|
||||
|
||||
lstDecks.setCaption(deckType.toString());
|
||||
|
||||
switch (deckType) {
|
||||
|
||||
@@ -52,7 +52,7 @@ public final class ItemListView<T extends InventoryItem> extends ItemView<T> {
|
||||
private final ItemTable table = new ItemTable();
|
||||
private final ItemTableModel tableModel;
|
||||
private boolean allowMultipleSelections;
|
||||
private List<Integer> selectedIndices;
|
||||
private List<Integer> selectedIndices = new ArrayList<Integer>();
|
||||
|
||||
public ItemTableModel getTableModel() {
|
||||
return tableModel;
|
||||
|
||||
@@ -25,6 +25,9 @@ import forge.game.GameFormat;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.guantlet.GauntletData;
|
||||
import forge.limited.GauntletMini;
|
||||
import forge.quest.QuestController;
|
||||
import forge.quest.QuestWorld;
|
||||
import forge.quest.data.QuestPreferences;
|
||||
import forge.toolbox.FProgressBar;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.storage.IStorage;
|
||||
@@ -55,19 +58,19 @@ public class FModel {
|
||||
private static PrintStream oldSystemErr;
|
||||
private static OutputStream logFileStream;
|
||||
|
||||
//private final QuestPreferences questPreferences;
|
||||
private static QuestPreferences questPreferences;
|
||||
private static ForgePreferences preferences;
|
||||
|
||||
// Someone should take care of 2 gauntlets here
|
||||
private static GauntletData gauntletData;
|
||||
private static GauntletMini gauntlet;
|
||||
|
||||
//private static QuestController quest;
|
||||
private static QuestController quest;
|
||||
private static CardCollections decks;
|
||||
|
||||
private static IStorage<CardBlock> blocks;
|
||||
private static IStorage<CardBlock> fantasyBlocks;
|
||||
//private static IStorage<QuestWorld> worlds;
|
||||
private static IStorage<QuestWorld> worlds;
|
||||
private static GameFormat.Collection formats;
|
||||
|
||||
public static void initialize(final FProgressBar progressBar) {
|
||||
@@ -145,25 +148,25 @@ public class FModel {
|
||||
|
||||
formats = new GameFormat.Collection(new GameFormat.Reader(new File(Constants.BLOCK_DATA_DIR + "formats.txt")));
|
||||
blocks = new StorageBase<CardBlock>("Block definitions", new CardBlock.Reader(Constants.BLOCK_DATA_DIR + "blocks.txt", magicDb.getEditions()));
|
||||
//questPreferences = new QuestPreferences();
|
||||
questPreferences = new QuestPreferences();
|
||||
gauntletData = new GauntletData();
|
||||
fantasyBlocks = new StorageBase<CardBlock>("Custom blocks", new CardBlock.Reader(Constants.BLOCK_DATA_DIR + "fantasyblocks.txt", magicDb.getEditions()));
|
||||
//worlds = new StorageBase<QuestWorld>("Quest worlds", new QuestWorld.Reader(Constants.QUEST_WORLD_DIR + "worlds.txt"));
|
||||
worlds = new StorageBase<QuestWorld>("Quest worlds", new QuestWorld.Reader(Constants.QUEST_WORLD_DIR + "worlds.txt"));
|
||||
|
||||
loadDynamicGamedata();
|
||||
|
||||
progressBar.setDescription("Loading decks");
|
||||
|
||||
decks = new CardCollections();
|
||||
//quest = new QuestController();
|
||||
quest = new QuestController();
|
||||
|
||||
//preload AI profiles
|
||||
AiProfileUtil.loadAllProfiles(Constants.AI_PROFILE_DIR);
|
||||
}
|
||||
|
||||
/*public static QuestController getQuest() {
|
||||
public static QuestController getQuest() {
|
||||
return quest;
|
||||
}*/
|
||||
}
|
||||
|
||||
private static boolean keywordsLoaded = false;
|
||||
|
||||
@@ -282,9 +285,9 @@ public class FModel {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
/*public static QuestPreferences getQuestPreferences() {
|
||||
public static QuestPreferences getQuestPreferences() {
|
||||
return questPreferences;
|
||||
}*/
|
||||
}
|
||||
|
||||
public static GauntletData getGauntletData() {
|
||||
return gauntletData;
|
||||
@@ -305,9 +308,9 @@ public class FModel {
|
||||
return decks;
|
||||
}
|
||||
|
||||
/*public static IStorage<QuestWorld> getWorlds() {
|
||||
public static IStorage<QuestWorld> getWorlds() {
|
||||
return worlds;
|
||||
}*/
|
||||
}
|
||||
|
||||
public static GameFormat.Collection getFormats() {
|
||||
return formats;
|
||||
|
||||
324
forge-m-base/src/forge/quest/BoosterUtils.java
Normal file
324
forge-m-base/src/forge/quest/BoosterUtils.java
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.card.MagicColor;
|
||||
import forge.card.PrintSheet;
|
||||
import forge.item.*;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.data.QuestPreferences.QPref;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
// The BoosterPack generates cards for the Card Pool in Quest Mode
|
||||
/**
|
||||
* <p>
|
||||
* QuestBoosterPack class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: BoosterUtils.java 24769 2014-02-09 13:56:04Z Hellfish $
|
||||
*/
|
||||
public final class BoosterUtils {
|
||||
|
||||
/**
|
||||
* Gets the quest starter deck.
|
||||
*
|
||||
* @param filter
|
||||
* the filter
|
||||
* @param numCommon
|
||||
* the num common
|
||||
* @param numUncommon
|
||||
* the num uncommon
|
||||
* @param numRare
|
||||
* the num rare
|
||||
* @param userPrefs
|
||||
* the starting pool preferences
|
||||
* @return the quest starter deck
|
||||
*/
|
||||
public static List<PaperCard> getQuestStarterDeck(final Predicate<PaperCard> filter, final int numCommon,
|
||||
final int numUncommon, final int numRare, final StartingPoolPreferences userPrefs) {
|
||||
|
||||
final ArrayList<PaperCard> cards = new ArrayList<PaperCard>();
|
||||
|
||||
// Each color should have around the same amount of monocolored cards
|
||||
// There should be 3 Colorless cards for every 4 cards in a single color
|
||||
// There should be 1 Multicolor card for every 4 cards in a single color
|
||||
|
||||
final List<Predicate<CardRules>> colorFilters = new ArrayList<Predicate<CardRules>>();
|
||||
final boolean preferred = (userPrefs != null && userPrefs.getPreferredColor() != MagicColor.ALL_COLORS);
|
||||
final boolean randomized = userPrefs != null && userPrefs.useRandomPool();
|
||||
final int colorBias = (preferred && !randomized) ? FModel.getQuestPreferences().getPrefInt(QPref.STARTING_POOL_COLOR_BIAS) : 0;
|
||||
final int biasAdjustedCommons = (((colorBias * numCommon) / 25) > 0 ? numCommon - (colorBias * numCommon) / 25 : numCommon);
|
||||
final int biasAdjustedUncommons = (((colorBias * numUncommon) / 25) > 0 ? numUncommon - (colorBias * numUncommon) / 25 : numUncommon);
|
||||
final int biasAdjustedRares = (((colorBias * numRare) / 25) > 0 ? numRare - (colorBias * numRare) / 25 : numRare);
|
||||
|
||||
if (!randomized) {
|
||||
colorFilters.add(CardRulesPredicates.Presets.IS_MULTICOLOR);
|
||||
|
||||
// extra filters of the preferred color if chosen
|
||||
if (preferred) {
|
||||
for (int i = 0; i < colorBias + (colorBias > 6 ? (2 * (colorBias - 6 + (colorBias / 10))) : 0); i++) {
|
||||
colorFilters.add(CardRulesPredicates.isMonoColor(userPrefs.getPreferredColor()));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < (preferred ? 3 : 4); i++) {
|
||||
if (i != 2) {
|
||||
colorFilters.add(CardRulesPredicates.Presets.IS_COLORLESS);
|
||||
}
|
||||
|
||||
colorFilters.add(CardRulesPredicates.isMonoColor(MagicColor.WHITE));
|
||||
colorFilters.add(CardRulesPredicates.isMonoColor(MagicColor.RED));
|
||||
colorFilters.add(CardRulesPredicates.isMonoColor(MagicColor.BLUE));
|
||||
colorFilters.add(CardRulesPredicates.isMonoColor(MagicColor.BLACK));
|
||||
colorFilters.add(CardRulesPredicates.isMonoColor(MagicColor.GREEN));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// This will save CPU time when sets are limited
|
||||
final List<PaperCard> cardpool = Lists.newArrayList(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), filter));
|
||||
|
||||
final Predicate<PaperCard> pCommon = IPaperCard.Predicates.Presets.IS_COMMON;
|
||||
cards.addAll(BoosterUtils.generateDefinetlyColouredCards(cardpool, pCommon, biasAdjustedCommons, colorFilters));
|
||||
|
||||
final Predicate<PaperCard> pUncommon = IPaperCard.Predicates.Presets.IS_UNCOMMON;
|
||||
cards.addAll(BoosterUtils.generateDefinetlyColouredCards(cardpool, pUncommon, biasAdjustedUncommons, colorFilters));
|
||||
|
||||
int nRares = biasAdjustedRares, nMythics = 0;
|
||||
final Predicate<PaperCard> filterMythics = IPaperCard.Predicates.Presets.IS_MYTHIC_RARE;
|
||||
final boolean haveMythics = Iterables.any(cardpool, filterMythics);
|
||||
for (int iSlot = 0; haveMythics && (iSlot < numRare); iSlot++) {
|
||||
if (MyRandom.getRandom().nextInt(10) < 1) {
|
||||
// 10% chance of upgrading a Rare into a Mythic
|
||||
nRares--;
|
||||
nMythics++;
|
||||
}
|
||||
}
|
||||
|
||||
final Predicate<PaperCard> pRare = IPaperCard.Predicates.Presets.IS_RARE;
|
||||
cards.addAll(BoosterUtils.generateDefinetlyColouredCards(cardpool, pRare, nRares, colorFilters));
|
||||
if (nMythics > 0) {
|
||||
cards.addAll(BoosterUtils.generateDefinetlyColouredCards(cardpool, filterMythics, nMythics, colorFilters));
|
||||
}
|
||||
return cards;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the list of card names at random from the given pool.
|
||||
*
|
||||
* @param source
|
||||
* an Iterable<CardPrinted>
|
||||
* @param filter
|
||||
* Predicate<CardPrinted>
|
||||
* @param cntNeeded
|
||||
* an int
|
||||
* @param allowedColors
|
||||
* a List<Predicate<CardRules>>
|
||||
* @return a list of card names
|
||||
*/
|
||||
private static ArrayList<PaperCard> generateDefinetlyColouredCards(final Iterable<PaperCard> source,
|
||||
final Predicate<PaperCard> filter, final int cntNeeded, final List<Predicate<CardRules>> allowedColors) {
|
||||
// If color is null, use colorOrder progression to grab cards
|
||||
final ArrayList<PaperCard> result = new ArrayList<PaperCard>();
|
||||
|
||||
final int size = allowedColors == null ? 0 : allowedColors.size();
|
||||
Collections.shuffle(allowedColors);
|
||||
|
||||
int cntMade = 0, iAttempt = 0;
|
||||
|
||||
// This will prevent endless loop @ wh
|
||||
int allowedMisses = (2 + size + 2) * cntNeeded; // lol, 2+2 is not magic
|
||||
// constant!
|
||||
|
||||
while ((cntMade < cntNeeded) && (allowedMisses > 0)) {
|
||||
PaperCard card = null;
|
||||
|
||||
if (size > 0) {
|
||||
final Predicate<CardRules> color2 = allowedColors.get(iAttempt % size);
|
||||
if (color2 != null) {
|
||||
Predicate<PaperCard> color2c = Predicates.compose(color2, PaperCard.FN_GET_RULES);
|
||||
card = Aggregates.random(Iterables.filter(source, Predicates.and(filter, color2c)));
|
||||
}
|
||||
}
|
||||
|
||||
if (card == null) {
|
||||
// We can't decide on a color, so just pick a card.
|
||||
card = Aggregates.random(Iterables.filter(source, filter));
|
||||
}
|
||||
|
||||
if ((card != null) && !result.contains(card)) {
|
||||
result.add(card);
|
||||
cntMade++;
|
||||
} else {
|
||||
allowedMisses--;
|
||||
}
|
||||
iAttempt++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse a limitation for a reward or chosen card.
|
||||
* @param input
|
||||
* String, the limitation as text.
|
||||
* @return Predicate<CardRules> the text parsed into a CardRules predicate.
|
||||
*
|
||||
*/
|
||||
public static Predicate<CardRules> parseRulesLimitation(final String input) {
|
||||
if (null == input || "random".equalsIgnoreCase(input)) {
|
||||
return Predicates.alwaysTrue();
|
||||
}
|
||||
|
||||
if (input.equalsIgnoreCase("black")) return CardRulesPredicates.Presets.IS_BLACK;
|
||||
if (input.equalsIgnoreCase("blue")) return CardRulesPredicates.Presets.IS_BLUE;
|
||||
if (input.equalsIgnoreCase("green")) return CardRulesPredicates.Presets.IS_GREEN;
|
||||
if (input.equalsIgnoreCase("red")) return CardRulesPredicates.Presets.IS_RED;
|
||||
if (input.equalsIgnoreCase("white")) return CardRulesPredicates.Presets.IS_WHITE;
|
||||
if (input.equalsIgnoreCase("colorless")) return CardRulesPredicates.Presets.IS_COLORLESS;
|
||||
if (input.equalsIgnoreCase("multicolor")) return CardRulesPredicates.Presets.IS_MULTICOLOR;
|
||||
|
||||
if (input.equalsIgnoreCase("land")) return CardRulesPredicates.Presets.IS_LAND;
|
||||
if (input.equalsIgnoreCase("creature")) return CardRulesPredicates.Presets.IS_CREATURE;
|
||||
if (input.equalsIgnoreCase("artifact")) return CardRulesPredicates.Presets.IS_ARTIFACT;
|
||||
if (input.equalsIgnoreCase("planeswalker")) return CardRulesPredicates.Presets.IS_PLANESWALKER;
|
||||
if (input.equalsIgnoreCase("instant")) return CardRulesPredicates.Presets.IS_INSTANT;
|
||||
if (input.equalsIgnoreCase("sorcery")) return CardRulesPredicates.Presets.IS_SORCERY;
|
||||
if (input.equalsIgnoreCase("enchantment")) return CardRulesPredicates.Presets.IS_ENCHANTMENT;
|
||||
|
||||
throw new IllegalArgumentException("No CardRules limitations could be parsed from: " + input);
|
||||
}
|
||||
/**
|
||||
* parseReward - used internally to parse individual items in a challenge reward definition.
|
||||
* @param s
|
||||
* String, the reward to parse
|
||||
* @return List<CardPrinted>
|
||||
*/
|
||||
private static List<InventoryItem> parseReward(final String s) {
|
||||
|
||||
String[] temp = s.split(" ");
|
||||
List<InventoryItem> rewards = new ArrayList<InventoryItem>();
|
||||
|
||||
// last word starts with 'rare' ignore case
|
||||
if (temp.length > 1 && temp[temp.length - 1].regionMatches(true, 0, "rare", 0, 4)) {
|
||||
// Type 1: 'n [color] rares'
|
||||
final int qty = Integer.parseInt(temp[0]);
|
||||
|
||||
List<Predicate<PaperCard>> preds = new ArrayList<Predicate<PaperCard>>();
|
||||
preds.add(IPaperCard.Predicates.Presets.IS_RARE_OR_MYTHIC); // Determine rarity
|
||||
|
||||
if (temp.length > 2) {
|
||||
Predicate<CardRules> cr = parseRulesLimitation(temp[1]);
|
||||
if (Predicates.alwaysTrue() != (Object) cr) { // guava has a single instance for always-const predicates
|
||||
preds.add(Predicates.compose(cr, PaperCard.FN_GET_RULES));
|
||||
}
|
||||
}
|
||||
|
||||
if (FModel.getQuest().getFormat() != null) {
|
||||
preds.add(FModel.getQuest().getFormat().getFilterPrinted());
|
||||
}
|
||||
|
||||
PrintSheet ps = new PrintSheet("Quest rewards");
|
||||
Predicate<PaperCard> predicate = preds.size() == 1 ? preds.get(0) : Predicates.and(preds);
|
||||
ps.addAll(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), predicate));
|
||||
rewards.addAll(ps.random(qty, true));
|
||||
} else if (temp.length == 2 && temp[0].equalsIgnoreCase("duplicate") && temp[1].equalsIgnoreCase("card")) {
|
||||
// Type 2: a duplicate card of the players choice
|
||||
rewards.add(new QuestRewardCardDuplicate());
|
||||
} else if (temp.length >= 2 && temp[0].equalsIgnoreCase("chosen") && temp[1].equalsIgnoreCase("card")) {
|
||||
// Type 3: a duplicate card of the players choice
|
||||
rewards.add(new QuestRewardCardFiltered(temp));
|
||||
} else if (temp.length >= 3 && temp[0].equalsIgnoreCase("booster") && temp[1].equalsIgnoreCase("pack")) {
|
||||
// Type 4: a predetermined extra booster pack
|
||||
rewards.add(BoosterPack.FN_FROM_SET.apply(FModel.getMagicDb().getEditions().get(temp[2])));
|
||||
} else if (temp.length >= 3 && temp[0].equalsIgnoreCase("tournament") && temp[1].equalsIgnoreCase("pack")) {
|
||||
// Type 5: a predetermined extra tournament ("starter") pack
|
||||
rewards.add(TournamentPack.FN_FROM_SET.apply(FModel.getMagicDb().getEditions().get(temp[2])));
|
||||
}
|
||||
else if (temp.length > 0) {
|
||||
// default: assume we are asking for a single copy of a specific card
|
||||
final PaperCard specific = FModel.getMagicDb().getCommonCards().getCard(s);
|
||||
if (specific != null) {
|
||||
rewards.add(specific);
|
||||
}
|
||||
}
|
||||
// Return the duplicate, a specified card, or an empty list
|
||||
return rewards;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* generateCardRewardList.
|
||||
* </p>
|
||||
* Takes a reward list string, parses, and returns list of cards rewarded.
|
||||
*
|
||||
* @param s
|
||||
* Properties string of reward (97 multicolor rares)
|
||||
* @return List<CardPrinted>
|
||||
*/
|
||||
public static List<InventoryItem> generateCardRewardList(final String s) {
|
||||
|
||||
if (StringUtils.isBlank(s)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String[] items = s.split(";");
|
||||
final List<InventoryItem> rewards = new ArrayList<InventoryItem>();
|
||||
|
||||
for (final String item : items) {
|
||||
|
||||
String input = null;
|
||||
|
||||
if (item.contains("%")) {
|
||||
String[] tmp = item.split("%");
|
||||
final int chance = Integer.parseInt(tmp[0].trim());
|
||||
if (chance > 0 && tmp.length > 1 && MyRandom.percentTrue(chance)) {
|
||||
input = tmp[1].trim();
|
||||
}
|
||||
} else {
|
||||
input = item;
|
||||
}
|
||||
if (input != null) {
|
||||
List<InventoryItem> reward = parseReward(input);
|
||||
|
||||
if (reward != null) {
|
||||
rewards.addAll(reward);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rewards;
|
||||
}
|
||||
}
|
||||
22
forge-m-base/src/forge/quest/IQuestRewardCard.java
Normal file
22
forge-m-base/src/forge/quest/IQuestRewardCard.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package forge.quest;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Various card rewards that may be awarded during the Quest.
|
||||
* Classes that implement this interface should be able to build
|
||||
* and return a list of card choices for the player to choose
|
||||
* from.
|
||||
*/
|
||||
public interface IQuestRewardCard extends InventoryItem {
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable list of card choices.
|
||||
* @return List<CardPrinted>, an umodifiable list of cards.
|
||||
*/
|
||||
List<PaperCard> getChoices();
|
||||
|
||||
}
|
||||
505
forge-m-base/src/forge/quest/QuestController.java
Normal file
505
forge-m-base/src/forge/quest/QuestController.java
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Nate
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import forge.deck.Deck;
|
||||
import forge.game.GameFormat;
|
||||
import forge.game.event.GameEvent;
|
||||
import forge.game.event.GameEventMulligan;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.PreconDeck;
|
||||
import forge.model.FModel;
|
||||
import forge.net.FServer;
|
||||
import forge.quest.bazaar.QuestBazaarManager;
|
||||
import forge.quest.bazaar.QuestItemType;
|
||||
import forge.quest.bazaar.QuestPetStorage;
|
||||
import forge.quest.data.GameFormatQuest;
|
||||
import forge.quest.data.QuestAchievements;
|
||||
import forge.quest.data.QuestAssets;
|
||||
import forge.quest.data.QuestData;
|
||||
import forge.quest.data.QuestPreferences.DifficultyPrefs;
|
||||
import forge.quest.io.QuestChallengeReader;
|
||||
import forge.util.storage.IStorage;
|
||||
import forge.util.storage.StorageBase;
|
||||
import forge.utils.Constants;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public class QuestController {
|
||||
|
||||
private QuestData model;
|
||||
// gadgets
|
||||
|
||||
// Utility class to access cards, has access to private fields
|
||||
// Moved some methods there that otherwise would make this class even more
|
||||
// complex
|
||||
private QuestUtilCards myCards;
|
||||
|
||||
private GameFormatQuest questFormat;
|
||||
|
||||
private QuestEvent currentEvent;
|
||||
|
||||
/** The decks. */
|
||||
private transient IStorage<Deck> decks;
|
||||
|
||||
private QuestEventDuelManager duelManager = null;
|
||||
private IStorage<QuestEventChallenge> allChallenges = null;
|
||||
|
||||
private QuestBazaarManager bazaar = null;
|
||||
|
||||
private QuestPetStorage pets = null;
|
||||
|
||||
// This is used by shop. Had no idea where else to place this
|
||||
private static transient IStorage<PreconDeck> preconManager = null;
|
||||
|
||||
/** The Constant RANK_TITLES. */
|
||||
public static final String[] RANK_TITLES = new String[] { "Level 0 - Confused Wizard", "Level 1 - Mana Mage",
|
||||
"Level 2 - Death by Megrim", "Level 3 - Shattered the Competition", "Level 4 - Black Knighted",
|
||||
"Level 5 - Shockingly Good", "Level 6 - Regressed into Timmy", "Level 7 - Loves Blue Control",
|
||||
"Level 8 - Immobilized by Fear", "Level 9 - Lands = Friends", "Level 10 - Forging new paths",
|
||||
"Level 11 - Infect-o-tron", "Level 12 - Great Balls of Fire", "Level 13 - Artifact Schmartifact",
|
||||
"Level 14 - Mike Mulligan's The Name", "Level 15 - Fresh Air: Good For The Health",
|
||||
"Level 16 - In It For The Love", "Level 17 - Sticks, Stones, Bones", "Level 18 - Credits For Breakfast",
|
||||
"Level 19 - Millasaurus", "Level 20 - One-turn Wonder", "Teaching Gandalf a Lesson",
|
||||
"What Do You Do With The Other Hand?", "Freelance Sorcerer, Works Weekends",
|
||||
"Should We Hire Commentators?", "Saltblasted For Your Talent", "Serra Angel Is Your Girlfriend", };
|
||||
|
||||
/** */
|
||||
public static final int MAX_PET_SLOTS = 2;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param slot   int
|
||||
* @param name   String
|
||||
*/
|
||||
public void selectPet(Integer slot, String name) {
|
||||
if (this.model != null) {
|
||||
this.model.getPetSlots().put(slot, name);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCharmState(boolean active) {
|
||||
if (this.model != null) {
|
||||
this.model.setCharmActive(active);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getCharmState() {
|
||||
return this.model == null ? false : this.model.isCharmActive();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param slot   int
|
||||
* @return String
|
||||
*/
|
||||
public String getSelectedPet(Integer slot) {
|
||||
return this.model == null ? null : this.model.getPetSlots().get(slot);
|
||||
}
|
||||
|
||||
// Cards - class uses data from here
|
||||
/**
|
||||
* Gets the cards.
|
||||
*
|
||||
* @return the cards
|
||||
*/
|
||||
public QuestUtilCards getCards() {
|
||||
return this.myCards;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the my decks.
|
||||
*
|
||||
* @return the myDecks
|
||||
*/
|
||||
public IStorage<Deck> getMyDecks() {
|
||||
return this.decks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current format if any.
|
||||
*
|
||||
* @return GameFormatQuest, the game format (if persistent).
|
||||
*/
|
||||
public GameFormatQuest getFormat() {
|
||||
|
||||
return (getWorldFormat() == null ? this.questFormat : getWorldFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the custom format for the main world, if any.
|
||||
*/
|
||||
public GameFormatQuest getMainFormat() {
|
||||
return this.questFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current event.
|
||||
*
|
||||
* @return the current event
|
||||
*/
|
||||
public QuestEvent getCurrentEvent() {
|
||||
return this.currentEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current event.
|
||||
*
|
||||
* @param currentEvent the new current event
|
||||
*/
|
||||
public void setCurrentEvent(final QuestEvent currentEvent) {
|
||||
this.currentEvent = currentEvent;
|
||||
}
|
||||
|
||||
public static IStorage<PreconDeck> getPrecons() {
|
||||
if (null == preconManager) {
|
||||
// read with a special class, that will fill sell rules as it processes each PreconDeck
|
||||
preconManager = new StorageBase<PreconDeck>("Quest shop decks", new PreconDeck.Reader(new File(Constants.QUEST_PRECON_DIR)){
|
||||
@Override
|
||||
protected PreconDeck getPreconDeckFromSections(java.util.Map<String,java.util.List<String>> sections) {
|
||||
PreconDeck result = super.getPreconDeckFromSections(sections);
|
||||
preconDeals.put(result.getName(), new SellRules(sections.get("shop")));
|
||||
return result;
|
||||
};
|
||||
});
|
||||
}
|
||||
return QuestController.preconManager;
|
||||
}
|
||||
private final static Map<String, SellRules> preconDeals = new TreeMap<String, SellRules>();
|
||||
public static SellRules getPreconDeals(PreconDeck deck) {
|
||||
return preconDeals.get(deck.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*
|
||||
* @param selectedQuest the selected quest
|
||||
*/
|
||||
public void load(final QuestData selectedQuest) {
|
||||
this.model = selectedQuest;
|
||||
// These are helper classes that hold no data.
|
||||
this.decks = this.model == null ? null : this.model.getAssets().getDeckStorage();
|
||||
this.myCards = this.model == null ? null : new QuestUtilCards(this);
|
||||
this.questFormat = this.model == null ? null : this.model.getFormat();
|
||||
this.currentEvent = null;
|
||||
|
||||
this.resetDuelsManager();
|
||||
this.resetChallengesManager();
|
||||
this.getDuelsManager().randomizeOpponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*/
|
||||
public void save() {
|
||||
if (this.model != null) {
|
||||
this.model.saveData();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* New game.
|
||||
*
|
||||
* @param name the name
|
||||
* @param difficulty
|
||||
* the difficulty
|
||||
* @param mode the mode
|
||||
* @param formatPrizes
|
||||
* prize boosters format
|
||||
* @param allowSetUnlocks
|
||||
* allow unlocking of sets
|
||||
* @param startingCards
|
||||
* the starting deck
|
||||
* @param formatStartingPool
|
||||
* format used for the starting pool
|
||||
* @param startingWorld
|
||||
* starting world
|
||||
* @param userPrefs
|
||||
* user preferences
|
||||
*/
|
||||
public void newGame(final String name, final int difficulty, final QuestMode mode,
|
||||
final GameFormat formatPrizes, final boolean allowSetUnlocks,
|
||||
final Deck startingCards, final GameFormat formatStartingPool,
|
||||
final String startingWorld, final StartingPoolPreferences userPrefs) {
|
||||
|
||||
this.load(new QuestData(name, difficulty, mode, formatPrizes, allowSetUnlocks, startingWorld)); // pass awards and unlocks here
|
||||
|
||||
if (startingCards != null) {
|
||||
this.myCards.addDeck(startingCards);
|
||||
}
|
||||
else {
|
||||
Predicate<PaperCard> filter = Predicates.alwaysTrue();
|
||||
if (formatStartingPool != null) {
|
||||
filter = formatStartingPool.getFilterPrinted();
|
||||
}
|
||||
this.myCards.setupNewGameCardPool(filter, difficulty, userPrefs);
|
||||
}
|
||||
|
||||
this.getAssets().setCredits(FModel.getQuestPreferences().getPrefInt(DifficultyPrefs.STARTING_CREDITS, difficulty));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rank.
|
||||
*
|
||||
* @return the rank
|
||||
*/
|
||||
public String getRank() {
|
||||
int level = this.model.getAchievements().getLevel();
|
||||
if (level >= QuestController.RANK_TITLES.length) {
|
||||
level = QuestController.RANK_TITLES.length - 1;
|
||||
}
|
||||
return QuestController.RANK_TITLES[level];
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*
|
||||
* @return the assets
|
||||
*/
|
||||
public QuestAssets getAssets() {
|
||||
return this.model == null ? null : this.model.getAssets();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the QuestWorld, if any.
|
||||
*
|
||||
* @return QuestWorld or null, if using regular duels and challenges.
|
||||
*/
|
||||
public QuestWorld getWorld() {
|
||||
return this.model == null || this.model.getWorldId() == null ? null : FModel.getWorlds().get(this.model.getWorldId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new QuestWorld.
|
||||
*
|
||||
* @param newWorld
|
||||
* string, the new world id
|
||||
*/
|
||||
public void setWorld(final QuestWorld newWorld) {
|
||||
if (this.model == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.model.setWorldId(newWorld == null ? null : newWorld.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the QuestWorld Format, if any.
|
||||
*
|
||||
* @return GameFormatQuest or null.
|
||||
*/
|
||||
public GameFormatQuest getWorldFormat() {
|
||||
if (this.model == null || this.model.getWorldId() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final QuestWorld curQw = FModel.getWorlds().get(this.model.getWorldId());
|
||||
|
||||
if (curQw == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return curQw.getFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return this.model == null ? null : this.model.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*
|
||||
* @return the achievements
|
||||
*/
|
||||
public QuestAchievements getAchievements() {
|
||||
return this.model == null ? null : this.model.getAchievements();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*
|
||||
* @return the mode
|
||||
*/
|
||||
public QuestMode getMode() {
|
||||
return this.model.getMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bazaar.
|
||||
*
|
||||
* @return the bazaar
|
||||
*/
|
||||
public final QuestBazaarManager getBazaar() {
|
||||
if (null == this.bazaar) {
|
||||
this.bazaar = new QuestBazaarManager(new File(Constants.BAZAAR_FILE));
|
||||
}
|
||||
return this.bazaar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the event manager.
|
||||
*
|
||||
* @return the event manager
|
||||
*/
|
||||
public QuestEventDuelManager getDuelsManager() {
|
||||
if (this.duelManager == null) {
|
||||
resetDuelsManager();
|
||||
}
|
||||
return this.duelManager;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* TODO: Write javadoc for this method.
|
||||
* @return QuestEventManager
|
||||
*/
|
||||
public IStorage<QuestEventChallenge> getChallenges() {
|
||||
if (this.allChallenges == null) {
|
||||
resetChallengesManager();
|
||||
}
|
||||
return this.allChallenges;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Reset the duels manager.
|
||||
*/
|
||||
public void resetDuelsManager() {
|
||||
QuestWorld world = getWorld();
|
||||
String path = world == null || world.getDuelsDir() == null ? Constants.DEFAULT_DUELS_DIR : "res/quest/world/" + world.getDuelsDir();
|
||||
this.duelManager = new QuestEventDuelManager(new File(path));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Reset the challenges manager.
|
||||
*/
|
||||
public void resetChallengesManager() {
|
||||
QuestWorld world = getWorld();
|
||||
String path = world == null || world.getChallengesDir() == null ? Constants.DEFAULT_CHALLENGES_DIR : "res/quest/world/" + world.getChallengesDir();
|
||||
this.allChallenges = new StorageBase<QuestEventChallenge>("Quest Challenges", new QuestChallengeReader(new File(path)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* TODO: Write javadoc for this method.
|
||||
* @return QuestPetStorage
|
||||
*/
|
||||
public QuestPetStorage getPetsStorage() {
|
||||
if (this.pets == null) {
|
||||
this.pets = new QuestPetStorage(new File(Constants.BAZAAR_FILE));
|
||||
}
|
||||
|
||||
return this.pets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quest format has unlockable sets available at the moment.
|
||||
* @return int number of unlockable sets.
|
||||
*/
|
||||
public int getUnlocksTokens() {
|
||||
if (this.questFormat == null || !this.questFormat.canUnlockSets()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final int wins = this.model.getAchievements().getWin();
|
||||
|
||||
int cntLocked = this.questFormat.getLockedSets().size();
|
||||
int unlocksAvaliable = wins / 20;
|
||||
int unlocksSpent = this.questFormat.getUnlocksUsed();
|
||||
|
||||
return unlocksAvaliable > unlocksSpent ? Math.min(unlocksAvaliable - unlocksSpent, cntLocked) : 0;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void receiveGameEvent(GameEvent ev) { // Receives events only during quest games
|
||||
if (ev instanceof GameEventMulligan) {
|
||||
GameEventMulligan mev = (GameEventMulligan) ev;
|
||||
// First mulligan is free
|
||||
if (mev.player.getLobbyPlayer() == FServer.getLobby().getQuestPlayer()
|
||||
&& getAssets().hasItem(QuestItemType.SLEIGHT) && mev.player.getStats().getMulliganCount() == 0) {
|
||||
mev.player.drawCard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getTurnsToUnlockChallenge() {
|
||||
if (FModel.getQuest().getAssets().hasItem(QuestItemType.ZEPPELIN)) {
|
||||
return 8;
|
||||
}
|
||||
// User may have MAP and ZEPPELIN, so MAP must be tested second.
|
||||
else if (FModel.getQuest().getAssets().hasItem(QuestItemType.MAP)) {
|
||||
return 9;
|
||||
}
|
||||
|
||||
return 10;
|
||||
}
|
||||
|
||||
public final void regenerateChallenges() {
|
||||
final QuestAchievements achievements = model.getAchievements();
|
||||
final List<String> unlockedChallengeIds = new ArrayList<String>();
|
||||
final List<String> availableChallengeIds = achievements.getCurrentChallenges();
|
||||
|
||||
int maxChallenges = achievements.getWin() / getTurnsToUnlockChallenge() - achievements.getChallengesPlayed();
|
||||
if (maxChallenges > 5) {
|
||||
maxChallenges = 5;
|
||||
}
|
||||
|
||||
// Generate IDs as needed.
|
||||
if (achievements.getCurrentChallenges().size() < maxChallenges) {
|
||||
for (final QuestEventChallenge qc : allChallenges) {
|
||||
if (qc.getWinsReqd() > achievements.getWin()) {
|
||||
continue;
|
||||
}
|
||||
if (!qc.isRepeatable() && achievements.getLockedChallenges().contains(qc.getId())) {
|
||||
continue;
|
||||
}
|
||||
if (!availableChallengeIds.contains(qc.getId())) {
|
||||
unlockedChallengeIds.add(qc.getId());
|
||||
}
|
||||
}
|
||||
|
||||
Collections.shuffle(unlockedChallengeIds);
|
||||
|
||||
maxChallenges = Math.min(maxChallenges, unlockedChallengeIds.size());
|
||||
|
||||
for (int i = availableChallengeIds.size(); i < maxChallenges; i++) {
|
||||
availableChallengeIds.add(unlockedChallengeIds.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
achievements.setCurrentChallenges(availableChallengeIds);
|
||||
save();
|
||||
}
|
||||
}
|
||||
59
forge-m-base/src/forge/quest/QuestDeckMap.java
Normal file
59
forge-m-base/src/forge/quest/QuestDeckMap.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import forge.deck.Deck;
|
||||
import forge.util.storage.StorageBase;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public class QuestDeckMap extends StorageBase<Deck> {
|
||||
|
||||
/**
|
||||
* Instantiates a new quest deck map.
|
||||
*/
|
||||
public QuestDeckMap(Map<String, Deck> in) {
|
||||
super("Quest decks", in);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.util.IFolderMap#add(forge.util.IHasName)
|
||||
*/
|
||||
@Override
|
||||
public void add(final Deck deck) {
|
||||
this.map.put(deck.getName(), deck);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see forge.util.IFolderMap#delete(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void delete(final String deckName) {
|
||||
this.map.remove(deckName);
|
||||
}
|
||||
|
||||
}
|
||||
131
forge-m-base/src/forge/quest/QuestEvent.java
Normal file
131
forge-m-base/src/forge/quest/QuestEvent.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import forge.deck.Deck;
|
||||
import forge.game.player.IHasIcon;
|
||||
import forge.item.InventoryItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestEvent.
|
||||
* </p>
|
||||
*
|
||||
* MODEL - A basic event instance in Quest mode. Can be extended for use in
|
||||
* unique event types: battles, quests, and others.
|
||||
*/
|
||||
public abstract class QuestEvent implements IHasIcon {
|
||||
// Default vals if none provided in the event file.
|
||||
private Deck eventDeck = null;
|
||||
private String title = "Mystery Event";
|
||||
private String description = "";
|
||||
private QuestEventDifficulty difficulty = QuestEventDifficulty.MEDIUM;
|
||||
private String imageKey = "";
|
||||
private String name = "Noname";
|
||||
private String cardReward = null;
|
||||
private List<InventoryItem> cardRewardList = null;
|
||||
|
||||
|
||||
public static final Function<QuestEvent, String> FN_GET_NAME = new Function<QuestEvent, String>() {
|
||||
@Override public final String apply(QuestEvent qe) { return qe.name; }
|
||||
};
|
||||
|
||||
public final String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null for standard quest events, may return something different for challenges.
|
||||
*/
|
||||
public String getOpponent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final QuestEventDifficulty getDifficulty() {
|
||||
return this.difficulty;
|
||||
}
|
||||
|
||||
public final String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public final Deck getEventDeck() {
|
||||
return this.eventDeck;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getIconImageKey() {
|
||||
return this.imageKey;
|
||||
}
|
||||
|
||||
public final String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(final String name0) {
|
||||
this.name = name0;
|
||||
}
|
||||
|
||||
public void setTitle(final String title0) {
|
||||
this.title = title0;
|
||||
}
|
||||
|
||||
public void setDifficulty(final QuestEventDifficulty difficulty0) {
|
||||
this.difficulty = difficulty0;
|
||||
}
|
||||
|
||||
public void setDescription(final String description0) {
|
||||
this.description = description0;
|
||||
}
|
||||
|
||||
public void setEventDeck(final Deck eventDeck0) {
|
||||
this.eventDeck = eventDeck0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIconImageKey(final String s0) {
|
||||
this.imageKey = s0;
|
||||
}
|
||||
|
||||
public final List<InventoryItem> getCardRewardList() {
|
||||
if (cardReward == null) {
|
||||
return null;
|
||||
}
|
||||
if (cardRewardList == null) {
|
||||
this.cardRewardList = new ArrayList<InventoryItem>(BoosterUtils.generateCardRewardList(cardReward));
|
||||
}
|
||||
return this.cardRewardList;
|
||||
}
|
||||
|
||||
public void setCardReward(final String cardReward0) {
|
||||
this.cardReward = cardReward0;
|
||||
}
|
||||
|
||||
public List<String> getHumanExtraCards() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public List<String> getAiExtraCards() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
315
forge-m-base/src/forge/quest/QuestEventChallenge.java
Normal file
315
forge-m-base/src/forge/quest/QuestEventChallenge.java
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import forge.deck.Deck;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestQuest class.
|
||||
* </p>
|
||||
*
|
||||
* MODEL - A single quest event data instance, including meta, deck, and
|
||||
* quest-specific properties.
|
||||
*
|
||||
*/
|
||||
public class QuestEventChallenge extends QuestEvent {
|
||||
public static final Function<QuestEventChallenge, String> FN_GET_ID = new Function<QuestEventChallenge, String>() {
|
||||
@Override public final String apply(QuestEventChallenge qe) { return qe.id; }
|
||||
};
|
||||
|
||||
// ID (default -1, should be explicitly set at later time.)
|
||||
/** The id. */
|
||||
private String id = "-1";
|
||||
|
||||
// Opponent name if different from the challenge name
|
||||
private String opponentName = null;
|
||||
|
||||
// Default vals if none provided for this ID
|
||||
/** The ai life. */
|
||||
private int aiLife = 25;
|
||||
|
||||
private Integer humanLife = null;
|
||||
|
||||
/** The credits reward. */
|
||||
private int creditsReward = 100;
|
||||
|
||||
/** The repeatable. */
|
||||
private boolean repeatable = false;
|
||||
|
||||
private boolean useBazaar = true;
|
||||
private Boolean forceAnte = null;
|
||||
|
||||
/** The wins reqd. */
|
||||
private int winsReqd = 20;
|
||||
|
||||
// Other cards used in assignment: starting, and reward.
|
||||
/** The human extra cards. */
|
||||
private List<String> humanExtraCards = new ArrayList<String>();
|
||||
|
||||
/** The ai extra cards. */
|
||||
private List<String> aiExtraCards = new ArrayList<String>();
|
||||
|
||||
private Deck humanDeck = null;
|
||||
|
||||
/**
|
||||
* Instantiates a new quest challenge.
|
||||
*/
|
||||
public QuestEventChallenge() {
|
||||
super();
|
||||
setCardReward("1 colorless rare"); // Guaranteed extra reward for challenges if not specified
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getAILife.
|
||||
* </p>
|
||||
*
|
||||
* @return {@link java.lang.Integer}.
|
||||
*/
|
||||
public final int getAILife() {
|
||||
return this.getAiLife();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getCreditsReward.
|
||||
* </p>
|
||||
*
|
||||
* @return {@link java.lang.Integer}.
|
||||
*/
|
||||
public final int getCreditsReward() {
|
||||
return this.creditsReward;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getId.
|
||||
* </p>
|
||||
*
|
||||
* @return {@link java.lang.Integer}.
|
||||
*/
|
||||
public final String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* get the opponent's name, or null if not explicitly set.
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @return {@link java.lang.String}.
|
||||
*/
|
||||
@Override
|
||||
public final String getOpponent() {
|
||||
return this.opponentName;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getWinsReqd.
|
||||
* </p>
|
||||
*
|
||||
* @return {@link java.lang.Integer}.
|
||||
*/
|
||||
public final int getWinsReqd() {
|
||||
return this.winsReqd;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getHumanExtraCards.
|
||||
* </p>
|
||||
* Retrieves list of cards human has in play at the beginning of this quest.
|
||||
*
|
||||
* @return the human extra cards
|
||||
*/
|
||||
@Override
|
||||
public final List<String> getHumanExtraCards() {
|
||||
return this.humanExtraCards;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ai extra cards.
|
||||
*
|
||||
* @return the aiExtraCards
|
||||
*/
|
||||
@Override
|
||||
public List<String> getAiExtraCards() {
|
||||
return this.aiExtraCards;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ai extra cards.
|
||||
*
|
||||
* @param aiExtraCards0
|
||||
* the aiExtraCards to set
|
||||
*/
|
||||
public void setAiExtraCards(final List<String> aiExtraCards0) {
|
||||
this.aiExtraCards = aiExtraCards0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the id.
|
||||
*
|
||||
* @param id0
|
||||
* the id to set
|
||||
*/
|
||||
public void setId(final String id0) {
|
||||
this.id = id0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the opponent's name.
|
||||
*
|
||||
* @param newName
|
||||
* the name to set
|
||||
*/
|
||||
public void setOpponent(final String newName) {
|
||||
this.opponentName = newName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is repeatable.
|
||||
*
|
||||
* @return the repeatable
|
||||
*/
|
||||
public boolean isRepeatable() {
|
||||
return this.repeatable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the repeatable.
|
||||
*
|
||||
* @param repeatable0
|
||||
* the repeatable to set
|
||||
*/
|
||||
public void setRepeatable(final boolean repeatable0) {
|
||||
this.repeatable = repeatable0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ai life.
|
||||
*
|
||||
* @return the aiLife
|
||||
*/
|
||||
public int getAiLife() {
|
||||
return this.aiLife;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ai life.
|
||||
*
|
||||
* @param aiLife0
|
||||
* the aiLife to set
|
||||
*/
|
||||
public void setAiLife(final int aiLife0) {
|
||||
this.aiLife = aiLife0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the wins reqd.
|
||||
*
|
||||
* @param winsReqd0
|
||||
* the winsReqd to set
|
||||
*/
|
||||
public void setWinsReqd(final int winsReqd0) {
|
||||
this.winsReqd = winsReqd0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the credits reward.
|
||||
*
|
||||
* @param creditsReward0
|
||||
* the creditsReward to set
|
||||
*/
|
||||
public void setCreditsReward(final int creditsReward0) {
|
||||
this.creditsReward = creditsReward0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the human extra cards.
|
||||
*
|
||||
* @param humanExtraCards0
|
||||
* the humanExtraCards to set
|
||||
*/
|
||||
public void setHumanExtraCards(final List<String> humanExtraCards0) {
|
||||
this.humanExtraCards = humanExtraCards0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the humanLife
|
||||
*/
|
||||
public Integer getHumanLife() {
|
||||
return humanLife;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param humanLife the humanLife to set
|
||||
*/
|
||||
public void setHumanLife(Integer humanLife) {
|
||||
this.humanLife = humanLife;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the useBazaar
|
||||
*/
|
||||
public boolean isUseBazaar() {
|
||||
return useBazaar;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param useBazaar the useBazaar to set
|
||||
*/
|
||||
public void setUseBazaar(boolean useBazaar) {
|
||||
this.useBazaar = useBazaar;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the forceAnte
|
||||
*/
|
||||
public Boolean isForceAnte() {
|
||||
return forceAnte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forceAnte the forceAnte to set
|
||||
*/
|
||||
public void setForceAnte(Boolean forceAnte) {
|
||||
this.forceAnte = forceAnte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the humanDeck
|
||||
*/
|
||||
public Deck getHumanDeck() {
|
||||
return humanDeck;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param humanDeck the humanDeck to set
|
||||
*/
|
||||
public void setHumanDeck(Deck humanDeck) {
|
||||
this.humanDeck = humanDeck;
|
||||
}
|
||||
}
|
||||
35
forge-m-base/src/forge/quest/QuestEventDifficulty.java
Normal file
35
forge-m-base/src/forge/quest/QuestEventDifficulty.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package forge.quest;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public enum QuestEventDifficulty {
|
||||
EASY("easy"),
|
||||
MEDIUM("medium"),
|
||||
HARD("hard"),
|
||||
EXPERT("very hard");
|
||||
|
||||
String inFile;
|
||||
|
||||
private QuestEventDifficulty(String storedInFile) {
|
||||
inFile = storedInFile;
|
||||
}
|
||||
|
||||
public final String getTitle() {
|
||||
return inFile;
|
||||
}
|
||||
|
||||
public static QuestEventDifficulty fromString(String src) {
|
||||
if ( StringUtils.isBlank(src) )
|
||||
return MEDIUM; // player have custom files, that didn't specify a valid difficulty
|
||||
|
||||
for(QuestEventDifficulty qd : QuestEventDifficulty.values()) {
|
||||
if( src.equalsIgnoreCase(qd.inFile) || src.equalsIgnoreCase(qd.name()) )
|
||||
return qd;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
37
forge-m-base/src/forge/quest/QuestEventDuel.java
Normal file
37
forge-m-base/src/forge/quest/QuestEventDuel.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestDuel class.
|
||||
* </p>
|
||||
* MODEL - A single duel event data instance, including meta and deck.
|
||||
*
|
||||
*/
|
||||
public class QuestEventDuel extends QuestEvent {
|
||||
|
||||
/**
|
||||
* Instantiates a new quest duel.
|
||||
*/
|
||||
public QuestEventDuel() {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
||||
158
forge-m-base/src/forge/quest/QuestEventDuelManager.java
Normal file
158
forge-m-base/src/forge/quest/QuestEventDuelManager.java
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import forge.model.FModel;
|
||||
import forge.quest.data.QuestPreferences;
|
||||
import forge.quest.data.QuestPreferences.DifficultyPrefs;
|
||||
import forge.quest.io.QuestDuelReader;
|
||||
import forge.util.CollectionSuppliers;
|
||||
import forge.util.maps.EnumMapOfLists;
|
||||
import forge.util.maps.MapOfLists;
|
||||
import forge.util.storage.IStorage;
|
||||
import forge.util.storage.StorageBase;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* QuestEventManager.
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestEventManager.java 20404 2013-03-17 05:34:13Z myk $
|
||||
*/
|
||||
public class QuestEventDuelManager {
|
||||
|
||||
private final MapOfLists<QuestEventDifficulty, QuestEventDuel> sortedDuels = new EnumMapOfLists<QuestEventDifficulty, QuestEventDuel>(QuestEventDifficulty.class, CollectionSuppliers.<QuestEventDuel>arrayLists());
|
||||
private final IStorage<QuestEventDuel> allDuels;
|
||||
|
||||
|
||||
/** Instantiate all events and difficulty lists.
|
||||
* @param dir   File object */
|
||||
public QuestEventDuelManager(final File dir) {
|
||||
allDuels = new StorageBase<QuestEventDuel>("Quest duels", new QuestDuelReader(dir));
|
||||
assembleDuelDifficultyLists();
|
||||
} // End assembleAllEvents()
|
||||
|
||||
/** @return List<QuestEventDuel> */
|
||||
public Iterable<QuestEventDuel> getAllDuels() {
|
||||
return allDuels;
|
||||
}
|
||||
|
||||
// define fallback orders if there aren't enough opponents defined for a particular difficultly level
|
||||
private static List<QuestEventDifficulty> _easyOrder = Arrays.asList(QuestEventDifficulty.EASY, QuestEventDifficulty.MEDIUM, QuestEventDifficulty.HARD, QuestEventDifficulty.EXPERT);
|
||||
private static List<QuestEventDifficulty> _mediumOrder = Arrays.asList(QuestEventDifficulty.MEDIUM, QuestEventDifficulty.HARD, QuestEventDifficulty.EASY, QuestEventDifficulty.EXPERT);
|
||||
private static List<QuestEventDifficulty> _hardOrder = Arrays.asList(QuestEventDifficulty.HARD, QuestEventDifficulty.MEDIUM, QuestEventDifficulty.EASY, QuestEventDifficulty.EXPERT);
|
||||
private static List<QuestEventDifficulty> _expertOrder = Arrays.asList(QuestEventDifficulty.EXPERT, QuestEventDifficulty.HARD, QuestEventDifficulty.MEDIUM, QuestEventDifficulty.EASY);
|
||||
|
||||
private void _addDuel(List<QuestEventDuel> outList, QuestEventDifficulty targetDifficulty, int toAdd) {
|
||||
// if there's no way we can satisfy the request, return now
|
||||
if (allDuels.size() <= toAdd) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<QuestEventDifficulty> difficultyOrder;
|
||||
switch (targetDifficulty) {
|
||||
case EASY: difficultyOrder = _easyOrder; break;
|
||||
case MEDIUM: difficultyOrder = _mediumOrder; break;
|
||||
case HARD: difficultyOrder = _hardOrder; break;
|
||||
case EXPERT: difficultyOrder = _expertOrder; break;
|
||||
default:
|
||||
throw new RuntimeException("unhandled difficulty: " + targetDifficulty);
|
||||
}
|
||||
|
||||
for (QuestEventDifficulty d : difficultyOrder) { // will add duels from preferred difficulty, will use others if the former has too few options.
|
||||
for( QuestEventDuel duel : sortedDuels.get(d)) {
|
||||
if(toAdd <= 0)
|
||||
return;
|
||||
|
||||
if (!outList.contains(duel)) {
|
||||
outList.add(duel);
|
||||
toAdd--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Generates an array of new duel opponents based on current win conditions.
|
||||
*
|
||||
* @return an array of {@link java.lang.String} objects.
|
||||
*/
|
||||
public final List<QuestEventDuel> generateDuels() {
|
||||
final QuestPreferences qpref = FModel.getQuestPreferences();
|
||||
if (FModel.getQuest().getAchievements() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final QuestController qCtrl = FModel.getQuest();
|
||||
final int cntWins = qCtrl.getAchievements().getWin();
|
||||
|
||||
final int index = qCtrl.getAchievements().getDifficulty();
|
||||
final List<QuestEventDuel> duelOpponents = new ArrayList<QuestEventDuel>();
|
||||
|
||||
if (cntWins < qpref.getPrefInt(DifficultyPrefs.WINS_MEDIUMAI, index)) {
|
||||
_addDuel(duelOpponents, QuestEventDifficulty.EASY, 3);
|
||||
} else if (cntWins == qpref.getPrefInt(DifficultyPrefs.WINS_MEDIUMAI, index)) {
|
||||
_addDuel(duelOpponents, QuestEventDifficulty.EASY, 1);
|
||||
_addDuel(duelOpponents, QuestEventDifficulty.MEDIUM, 2);
|
||||
} else if (cntWins < qpref.getPrefInt(DifficultyPrefs.WINS_HARDAI, index)) {
|
||||
_addDuel(duelOpponents, QuestEventDifficulty.MEDIUM, 3);
|
||||
} else if (cntWins == qpref.getPrefInt(DifficultyPrefs.WINS_HARDAI, index)) {
|
||||
_addDuel(duelOpponents, QuestEventDifficulty.MEDIUM, 1);
|
||||
_addDuel(duelOpponents, QuestEventDifficulty.HARD, 2);
|
||||
} else if (cntWins < qpref.getPrefInt(DifficultyPrefs.WINS_EXPERTAI, index)) {
|
||||
_addDuel(duelOpponents, QuestEventDifficulty.HARD, 3);
|
||||
} else {
|
||||
_addDuel(duelOpponents, QuestEventDifficulty.HARD, 2);
|
||||
_addDuel(duelOpponents, QuestEventDifficulty.EXPERT, 1);
|
||||
}
|
||||
|
||||
return duelOpponents;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* assembleDuelDifficultyLists.
|
||||
* </p>
|
||||
* Assemble duel deck difficulty lists
|
||||
*/
|
||||
private void assembleDuelDifficultyLists() {
|
||||
sortedDuels.clear();
|
||||
sortedDuels.put(QuestEventDifficulty.EASY, new ArrayList<QuestEventDuel>());
|
||||
sortedDuels.put(QuestEventDifficulty.MEDIUM, new ArrayList<QuestEventDuel>());
|
||||
sortedDuels.put(QuestEventDifficulty.HARD, new ArrayList<QuestEventDuel>());
|
||||
sortedDuels.put(QuestEventDifficulty.EXPERT, new ArrayList<QuestEventDuel>());
|
||||
|
||||
|
||||
|
||||
for (final QuestEventDuel qd : allDuels) {
|
||||
sortedDuels.add(qd.getDifficulty(), qd);
|
||||
}
|
||||
}
|
||||
|
||||
/** */
|
||||
public void randomizeOpponents() {
|
||||
final long seed = new Random().nextLong();
|
||||
final Random r = new Random(seed);
|
||||
for(QuestEventDifficulty qd : sortedDuels.keySet()) {
|
||||
List<QuestEventDuel> list = (List<QuestEventDuel>) sortedDuels.get(qd);
|
||||
Collections.shuffle(list, r);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
34
forge-m-base/src/forge/quest/QuestMode.java
Normal file
34
forge-m-base/src/forge/quest/QuestMode.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package forge.quest;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
|
||||
public enum QuestMode {
|
||||
// Do not apply checkstyle here, to maintain compatibility with old saves
|
||||
Fantasy,
|
||||
Classic,
|
||||
Gauntlet;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param value
|
||||
* @param classic2
|
||||
* @return
|
||||
*/
|
||||
public static QuestMode smartValueOf(String value, QuestMode defaultValue) {
|
||||
if (null == value) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
final String valToCompate = value.trim();
|
||||
for (final QuestMode v : QuestMode.values()) {
|
||||
if (v.name().compareToIgnoreCase(valToCompate) == 0) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
return QuestMode.Classic;
|
||||
}
|
||||
}
|
||||
123
forge-m-base/src/forge/quest/QuestRewardCard.java
Normal file
123
forge-m-base/src/forge/quest/QuestRewardCard.java
Normal file
@@ -0,0 +1,123 @@
|
||||
package forge.quest;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
|
||||
import forge.card.CardRules;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public abstract class QuestRewardCard implements InventoryItem, IQuestRewardCard {
|
||||
|
||||
protected String buildDescription(final String [] input) {
|
||||
final String defaultDescription = "a card";
|
||||
if (input == null || input.length < 1) {
|
||||
return defaultDescription;
|
||||
}
|
||||
|
||||
String buildDesc = null;
|
||||
|
||||
for (String s : input) {
|
||||
if (s.startsWith("desc:") || s.startsWith("Desc:")) {
|
||||
String[] tmp = s.split(":");
|
||||
if (tmp.length > 1) {
|
||||
buildDesc = new String(tmp[1]);
|
||||
} else {
|
||||
buildDesc = new String();
|
||||
}
|
||||
} else if (buildDesc != null) {
|
||||
if (s.contains(":")) {
|
||||
return buildDesc;
|
||||
} else {
|
||||
buildDesc = buildDesc + " " + s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buildDesc != null) {
|
||||
return buildDesc;
|
||||
}
|
||||
return defaultDescription;
|
||||
}
|
||||
|
||||
protected Predicate<PaperCard> buildPredicates(final String [] input) {
|
||||
if (input == null || input.length < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Predicate<PaperCard> filters = FModel.getQuest().getFormat().getFilterPrinted();
|
||||
Predicate<CardRules> filterRules = null;
|
||||
Predicate<PaperCard> filterRarity = null;
|
||||
|
||||
for (String s : input) {
|
||||
if (s.startsWith("sets:") || s.startsWith("Sets:")) {
|
||||
final String[] tmp = s.split(":");
|
||||
if (tmp.length > 1) {
|
||||
String [] setcodes = tmp[1].split(",");
|
||||
if (setcodes.length > 0) {
|
||||
List<String> sets = new ArrayList<String>();
|
||||
for (String code : setcodes) {
|
||||
if (FModel.getMagicDb().getEditions().contains(code)) {
|
||||
// System.out.println("Set " + code + " was found!");
|
||||
sets.add(code);
|
||||
}
|
||||
// else { System.out.println("Unknown set code " + code); }
|
||||
}
|
||||
if (sets.size() > 0) {
|
||||
filters = IPaperCard.Predicates.printedInSets(sets, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (s.startsWith("rules:") || s.startsWith("Rules:")) {
|
||||
final String[] tmp = s.split(":");
|
||||
if (tmp.length > 1) {
|
||||
String [] ruleCodes = tmp[1].split(",");
|
||||
if (ruleCodes.length > 0) {
|
||||
for (String rule : ruleCodes) {
|
||||
final Predicate<CardRules> newRule = BoosterUtils.parseRulesLimitation(rule);
|
||||
if (newRule != null) {
|
||||
filterRules = (filterRules == null ? newRule : Predicates.and(filterRules, newRule));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (s.startsWith("rarity:") || s.startsWith("Rarity:")) {
|
||||
final String[] tmp = s.split(":");
|
||||
if (tmp.length > 1) {
|
||||
String [] rarityCodes = tmp[1].split(",");
|
||||
if (rarityCodes.length > 0) {
|
||||
for (String rarity : rarityCodes) {
|
||||
if (rarity.startsWith("C") || rarity.startsWith("c")) {
|
||||
filterRarity = (filterRarity == null ? IPaperCard.Predicates.Presets.IS_COMMON : Predicates.or(filterRarity, IPaperCard.Predicates.Presets.IS_COMMON));
|
||||
} else if (rarity.startsWith("U") || rarity.startsWith("u")) {
|
||||
filterRarity = (filterRarity == null ? IPaperCard.Predicates.Presets.IS_UNCOMMON : Predicates.or(filterRarity, IPaperCard.Predicates.Presets.IS_UNCOMMON));
|
||||
} else if (rarity.startsWith("R") || rarity.startsWith("r")) {
|
||||
filterRarity = (filterRarity == null ? IPaperCard.Predicates.Presets.IS_RARE : Predicates.or(filterRarity, IPaperCard.Predicates.Presets.IS_RARE));
|
||||
} else if (rarity.startsWith("M") || rarity.startsWith("m")) {
|
||||
filterRarity = (filterRarity == null ? IPaperCard.Predicates.Presets.IS_MYTHIC_RARE : Predicates.or(filterRarity, IPaperCard.Predicates.Presets.IS_MYTHIC_RARE));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (filterRules != null) {
|
||||
final Predicate<PaperCard> rulesPrinted = Predicates.compose(filterRules, PaperCard.FN_GET_RULES);
|
||||
filters = Predicates.and(filters, rulesPrinted);
|
||||
}
|
||||
if (filterRarity != null) {
|
||||
filters = Predicates.and(filters, filterRarity);
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
public abstract List<PaperCard> getChoices();
|
||||
|
||||
}
|
||||
125
forge-m-base/src/forge/quest/QuestRewardCardChooser.java
Normal file
125
forge-m-base/src/forge/quest/QuestRewardCardChooser.java
Normal file
@@ -0,0 +1,125 @@
|
||||
package forge.quest;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.util.ItemPool;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Resolves a card chooser InventoryItem into a CardPrinted.
|
||||
* The initial version includes "duplicate", other type may be added later.
|
||||
*
|
||||
*/
|
||||
public class QuestRewardCardChooser extends QuestRewardCard implements InventoryItem {
|
||||
/**
|
||||
* Possible types for this object.
|
||||
*/
|
||||
public enum poolType {
|
||||
/** The player's own cardpool (duplicate card). */
|
||||
playerCards,
|
||||
/** Filtered by a predicate that will be parsed. */
|
||||
predicateFilter
|
||||
}
|
||||
|
||||
private poolType type;
|
||||
private final String description;
|
||||
private final Predicate<PaperCard> predicates;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
* The parameter indicates the more specific type.
|
||||
* @param setType String, the type of the choosable card.
|
||||
* @param creationParameters String, used to build the predicates and description for the predicateFilter type
|
||||
*/
|
||||
public QuestRewardCardChooser(final poolType setType, final String[] creationParameters) {
|
||||
type = setType;
|
||||
if (type == poolType.playerCards) {
|
||||
description = "a duplicate card";
|
||||
predicates = null;
|
||||
} else {
|
||||
description = buildDescription(creationParameters);
|
||||
predicates = buildPredicates(creationParameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The name.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* The item type.
|
||||
*
|
||||
* @return item type
|
||||
*/
|
||||
@Override
|
||||
public String getItemType() {
|
||||
switch (type) {
|
||||
case playerCards:
|
||||
return "duplicate card";
|
||||
case predicateFilter: default:
|
||||
return "chosen card";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type as enum.
|
||||
* @return enum, item type.
|
||||
*/
|
||||
public poolType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a list of options to choose from.
|
||||
*
|
||||
* @return a List<CardPrinted> or null if could not create a list.
|
||||
*/
|
||||
@Override
|
||||
public final List<PaperCard> getChoices() {
|
||||
if (type == poolType.playerCards) {
|
||||
final ItemPool<PaperCard> playerCards = FModel.getQuest().getAssets().getCardPool();
|
||||
if (!playerCards.isEmpty()) { // Maybe a redundant check since it's hard to win a duel without any cards...
|
||||
|
||||
List<PaperCard> cardChoices = new ArrayList<PaperCard>();
|
||||
for (final Map.Entry<PaperCard, Integer> card : playerCards) {
|
||||
cardChoices.add(card.getKey());
|
||||
}
|
||||
Collections.sort(cardChoices);
|
||||
|
||||
return Collections.unmodifiableList(cardChoices);
|
||||
}
|
||||
|
||||
} else if (type == poolType.predicateFilter) {
|
||||
List<PaperCard> cardChoices = new ArrayList<PaperCard>();
|
||||
|
||||
for (final PaperCard card : Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), predicates)) {
|
||||
cardChoices.add(card);
|
||||
}
|
||||
Collections.sort(cardChoices);
|
||||
|
||||
return Collections.unmodifiableList(cardChoices);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown QuestRewardCardType: " + type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
72
forge-m-base/src/forge/quest/QuestRewardCardDuplicate.java
Normal file
72
forge-m-base/src/forge/quest/QuestRewardCardDuplicate.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package forge.quest;
|
||||
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.util.ItemPool;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Allows the player to choose a duplicate copy of a currently owned card.
|
||||
*
|
||||
*/
|
||||
public class QuestRewardCardDuplicate implements IQuestRewardCard {
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
*
|
||||
* The constructor. No parameters.
|
||||
*/
|
||||
public QuestRewardCardDuplicate() {
|
||||
description = "a duplicate card";
|
||||
}
|
||||
|
||||
/**
|
||||
* The name.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* The item type.
|
||||
*
|
||||
* @return item type
|
||||
*/
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return "duplicate card";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a list of options to choose from, in this case,
|
||||
* the player's current cards.
|
||||
*
|
||||
* @return a List<CardPrinted> or null if could not create a list.
|
||||
*/
|
||||
public final List<PaperCard> getChoices() {
|
||||
final ItemPool<PaperCard> playerCards = FModel.getQuest().getAssets().getCardPool();
|
||||
if (!playerCards.isEmpty()) { // Maybe a redundant check since it's hard to win a duel without any cards...
|
||||
|
||||
List<PaperCard> cardChoices = new ArrayList<PaperCard>();
|
||||
for (final Map.Entry<PaperCard, Integer> card : playerCards) {
|
||||
cardChoices.add(card.getKey());
|
||||
}
|
||||
Collections.sort(cardChoices);
|
||||
|
||||
return Collections.unmodifiableList(cardChoices);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
71
forge-m-base/src/forge/quest/QuestRewardCardFiltered.java
Normal file
71
forge-m-base/src/forge/quest/QuestRewardCardFiltered.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package forge.quest;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Allows the player to choose a card from a predicate-filtered list of cards.
|
||||
*
|
||||
*/
|
||||
public class QuestRewardCardFiltered extends QuestRewardCard implements IQuestRewardCard {
|
||||
private final String description;
|
||||
private final Predicate<PaperCard> predicates;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
* @param creationParameters String, used to build the predicates and description for the predicateFilter type
|
||||
*/
|
||||
public QuestRewardCardFiltered(final String[] creationParameters) {
|
||||
description = buildDescription(creationParameters);
|
||||
predicates = buildPredicates(creationParameters);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The name.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* The item type.
|
||||
*
|
||||
* @return item type
|
||||
*/
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return "chosen card";
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a list of options to choose from.
|
||||
*
|
||||
* @return a List<CardPrinted> or null if could not create a list.
|
||||
*/
|
||||
@Override
|
||||
public final List<PaperCard> getChoices() {
|
||||
List<PaperCard> cardChoices = new ArrayList<PaperCard>();
|
||||
for (final PaperCard card : Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), predicates)) {
|
||||
cardChoices.add(card);
|
||||
}
|
||||
Collections.sort(cardChoices);
|
||||
return Collections.unmodifiableList(cardChoices);
|
||||
}
|
||||
|
||||
}
|
||||
174
forge-m-base/src/forge/quest/QuestUtil.java
Normal file
174
forge-m-base/src/forge/quest/QuestUtil.java
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import forge.card.CardDb.SetPreference;
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardRules;
|
||||
import forge.game.card.Card;
|
||||
import forge.item.IPaperCard;
|
||||
import forge.item.PaperToken;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.bazaar.QuestPetController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestUtil class.
|
||||
* </p>
|
||||
* MODEL - Static utility methods to help with minor tasks around Quest.
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestUtil.java 24769 2014-02-09 13:56:04Z Hellfish $
|
||||
*/
|
||||
public class QuestUtil {
|
||||
/**
|
||||
* <p>
|
||||
* getComputerStartingCards.
|
||||
* </p>
|
||||
*
|
||||
* @param qd
|
||||
* a {@link forge.quest.data.QuestData} object.
|
||||
* @return a {@link forge.CardList} object.
|
||||
*/
|
||||
public static List<Card> getComputerStartingCards() {
|
||||
return new ArrayList<Card>();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getComputerStartingCards.
|
||||
* </p>
|
||||
* Returns new card instances of extra AI cards in play at start of event.
|
||||
*
|
||||
* @param qd
|
||||
* a {@link forge.quest.data.QuestData} object.
|
||||
* @param qe
|
||||
* a {@link forge.quest.QuestEvent} object.
|
||||
* @return a {@link forge.CardList} object.
|
||||
*/
|
||||
public static List<IPaperCard> getComputerStartingCards(final QuestEvent qe) {
|
||||
final List<IPaperCard> list = new ArrayList<IPaperCard>();
|
||||
|
||||
for (final String s : qe.getAiExtraCards()) {
|
||||
list.add(QuestUtil.readExtraCard(s));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getHumanStartingCards.
|
||||
* </p>
|
||||
* Returns list of current plant/pet configuration only.
|
||||
* @param human
|
||||
*
|
||||
* @param qd
|
||||
* a {@link forge.quest.data.QuestData} object.
|
||||
* @return a {@link forge.CardList} object.
|
||||
*/
|
||||
public static List<IPaperCard> getHumanStartingCards(final QuestController qc) {
|
||||
final List<IPaperCard> list = new ArrayList<IPaperCard>();
|
||||
|
||||
for (int iSlot = 0; iSlot < QuestController.MAX_PET_SLOTS; iSlot++) {
|
||||
String petName = qc.getSelectedPet(iSlot);
|
||||
QuestPetController pet = qc.getPetsStorage().getPet(petName);
|
||||
if (pet != null) {
|
||||
IPaperCard c = pet.getPetCard(qc.getAssets());
|
||||
if (c != null) {
|
||||
list.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getHumanStartingCards.
|
||||
* </p>
|
||||
* Returns new card instances of extra human cards, including current
|
||||
* plant/pet configuration, and cards in play at start of quest.
|
||||
*
|
||||
* @param qd
|
||||
* a {@link forge.quest.data.QuestData} object.
|
||||
* @param qe
|
||||
* a {@link forge.quest.QuestEvent} object.
|
||||
* @return a {@link forge.CardList} object.
|
||||
*/
|
||||
public static List<IPaperCard> getHumanStartingCards(final QuestController qc, final QuestEvent qe) {
|
||||
final List<IPaperCard> list = QuestUtil.getHumanStartingCards(qc);
|
||||
for (final String s : qe.getHumanExtraCards()) {
|
||||
list.add(QuestUtil.readExtraCard(s));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* createToken.
|
||||
* </p>
|
||||
* Creates a card instance for token defined by property string.
|
||||
*
|
||||
* @param s
|
||||
* Properties string of token
|
||||
* (TOKEN;W;1;1;sheep;type;type;type...)
|
||||
* @return token Card
|
||||
*/
|
||||
public static PaperToken createToken(final String s) {
|
||||
final String[] properties = s.split(";", 6);
|
||||
|
||||
List<String> script = new ArrayList<String>();
|
||||
script.add("Name:" + properties[4]);
|
||||
script.add("Colors:" + properties[1]);
|
||||
script.add("PT:"+ properties[2] + "/" + properties[3]);
|
||||
script.add("Types:" + properties[5].replace(';', ' '));
|
||||
script.add("Oracle:"); // tokens don't have texts yet
|
||||
String fileName = PaperToken.makeTokenFileName(properties[1], properties[2], properties[3], properties[4]);
|
||||
final PaperToken c = new PaperToken(CardRules.fromScript(script), CardEdition.UNKNOWN, fileName);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* readExtraCard.
|
||||
* </p>
|
||||
* Creates single card for a string read from unique event properties.
|
||||
*
|
||||
* @param name
|
||||
* the name
|
||||
* @param owner
|
||||
* the owner
|
||||
* @return the card
|
||||
*/
|
||||
public static IPaperCard readExtraCard(final String name) {
|
||||
// Token card creation
|
||||
IPaperCard tempcard;
|
||||
if (name.startsWith("TOKEN")) {
|
||||
tempcard = QuestUtil.createToken(name);
|
||||
return tempcard;
|
||||
}
|
||||
// Standard card creation
|
||||
return FModel.getMagicDb().getCommonCards().getCardFromEdition(name, SetPreference.Latest);
|
||||
}
|
||||
|
||||
} // QuestUtil
|
||||
708
forge-m-base/src/forge/quest/QuestUtilCards.java
Normal file
708
forge-m-base/src/forge/quest/QuestUtilCards.java
Normal file
@@ -0,0 +1,708 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.*;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckSection;
|
||||
import forge.game.GameFormat;
|
||||
import forge.item.*;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.bazaar.QuestItemType;
|
||||
import forge.quest.data.GameFormatQuest;
|
||||
import forge.quest.data.QuestAssets;
|
||||
import forge.quest.data.QuestPreferences;
|
||||
import forge.quest.data.QuestPreferences.DifficultyPrefs;
|
||||
import forge.quest.data.QuestPreferences.QPref;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.ItemPool;
|
||||
import forge.util.MyRandom;
|
||||
import forge.utils.ForgePreferences.FPref;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* This is a helper class to execute operations on QuestData. It has been
|
||||
* created to decrease complexity of questData class
|
||||
*/
|
||||
public final class QuestUtilCards {
|
||||
private final QuestController qc;
|
||||
private final QuestPreferences qpref;
|
||||
private final QuestAssets qa;
|
||||
|
||||
/**
|
||||
* Instantiates a new quest util cards.
|
||||
*
|
||||
* @param qd
|
||||
* the qd
|
||||
*/
|
||||
public QuestUtilCards(final QuestController qd) {
|
||||
this.qc = qd;
|
||||
this.qa = qc.getAssets();
|
||||
this.qpref = FModel.getQuestPreferences();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the basic lands (from random sets as limited by the format).
|
||||
*
|
||||
* @param nBasic the n basic
|
||||
* @param nSnow the n snow
|
||||
* @param usedFormat currently enforced game format, if any
|
||||
* @return the item pool view
|
||||
*/
|
||||
public static ItemPool<PaperCard> generateBasicLands(final int nBasic, final int nSnow, final GameFormatQuest usedFormat) {
|
||||
final ICardDatabase db = FModel.getMagicDb().getCommonCards();
|
||||
final ItemPool<PaperCard> pool = new ItemPool<PaperCard>(PaperCard.class);
|
||||
|
||||
List<String> landCodes = new ArrayList<String>();
|
||||
List<String> snowLandCodes = new ArrayList<String>();
|
||||
|
||||
if (usedFormat != null) {
|
||||
List<String> availableEditions = usedFormat.getAllowedSetCodes();
|
||||
|
||||
for (String edCode : availableEditions) {
|
||||
CardEdition ed = FModel.getMagicDb().getEditions().get(edCode);
|
||||
// Duel decks might have only 2 types of basic lands
|
||||
if (CardEdition.Predicates.hasBasicLands.apply(ed)) {
|
||||
landCodes.add(edCode);
|
||||
}
|
||||
}
|
||||
if (usedFormat.isSetLegal("ICE")) {
|
||||
snowLandCodes.add("ICE");
|
||||
}
|
||||
if (usedFormat.isSetLegal("CSP")) {
|
||||
snowLandCodes.add("CSP");
|
||||
}
|
||||
} else {
|
||||
Iterable<CardEdition> allEditions = FModel.getMagicDb().getEditions();
|
||||
for (CardEdition edition : Iterables.filter(allEditions, CardEdition.Predicates.hasBasicLands)) {
|
||||
landCodes.add(edition.getCode());
|
||||
}
|
||||
snowLandCodes.add("ICE");
|
||||
snowLandCodes.add("CSP");
|
||||
}
|
||||
|
||||
String landCode = Aggregates.random(landCodes);
|
||||
if (null == landCode) {
|
||||
landCode = "M10";
|
||||
}
|
||||
|
||||
final boolean isZendikarSet = landCode.equals("ZEN"); // we want to generate one kind of Zendikar lands at a time only
|
||||
final boolean zendikarSetMode = MyRandom.getRandom().nextBoolean();
|
||||
|
||||
for (String landName : MagicColor.Constant.BASIC_LANDS) {
|
||||
int artCount = db.getArtCount(landName, landCode);
|
||||
|
||||
if (FModel.getPreferences().getPrefBoolean(FPref.UI_RANDOM_ART_IN_POOLS)) {
|
||||
int[] artGroups = MyRandom.splitIntoRandomGroups(nBasic, isZendikarSet ? 4 : artCount);
|
||||
|
||||
for (int i = 1; i <= artGroups.length; i++) {
|
||||
pool.add(db.getCard(landName, landCode, isZendikarSet ? (zendikarSetMode ? i : i + 4) : i), artGroups[i - 1]);
|
||||
}
|
||||
} else {
|
||||
pool.add(db.getCard(landName, landCode, artCount > 1 ? MyRandom.getRandom().nextInt(artCount) + 1 : 1), nBasic);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!snowLandCodes.isEmpty()) {
|
||||
String snowLandCode = Aggregates.random(snowLandCodes);
|
||||
for (String landName : MagicColor.Constant.SNOW_LANDS) {
|
||||
pool.add(db.getCard(landName, snowLandCode), nSnow);
|
||||
}
|
||||
}
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* addCards.
|
||||
* </p>
|
||||
*
|
||||
* @param fSets
|
||||
* the f sets
|
||||
* @return the array list
|
||||
*/
|
||||
public List<PaperCard> generateQuestBooster(final Predicate<PaperCard> fSets) {
|
||||
UnOpenedProduct unopened = new UnOpenedProduct(getBoosterTemplate(), fSets);
|
||||
return unopened.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the all cards.
|
||||
*
|
||||
* @param newCards
|
||||
* the new cards
|
||||
*/
|
||||
public void addAllCards(final Iterable<PaperCard> newCards) {
|
||||
for (final PaperCard card : newCards) {
|
||||
this.addSingleCard(card, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the single card.
|
||||
*
|
||||
* @param card
|
||||
* the card
|
||||
* @param qty
|
||||
* quantity
|
||||
*/
|
||||
public void addSingleCard(final PaperCard card, int qty) {
|
||||
this.qa.getCardPool().add(card, qty);
|
||||
|
||||
// register card into that list so that it would appear as a new one.
|
||||
this.qa.getNewCardList().add(card, qty);
|
||||
}
|
||||
|
||||
private static final Predicate<PaperCard> RARE_PREDICATE = IPaperCard.Predicates.Presets.IS_RARE_OR_MYTHIC;
|
||||
|
||||
|
||||
/**
|
||||
* A predicate that takes into account the Quest Format (if any).
|
||||
* @param source
|
||||
* the predicate to be added to the format predicate.
|
||||
* @return the composite predicate.
|
||||
*/
|
||||
public Predicate<PaperCard> applyFormatFilter(Predicate<PaperCard> source) {
|
||||
return qc.getFormat() == null ? source : Predicates.and(source, qc.getFormat().getFilterPrinted());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the random rare.
|
||||
*
|
||||
* @return the card printed
|
||||
*/
|
||||
public PaperCard addRandomRare() {
|
||||
|
||||
final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.RARE_PREDICATE);
|
||||
|
||||
final PaperCard card = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter));
|
||||
this.addSingleCard(card, 1);
|
||||
return card;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the random rare.
|
||||
*
|
||||
* @param n
|
||||
* the n
|
||||
* @return the list
|
||||
*/
|
||||
public List<PaperCard> addRandomRare(final int n) {
|
||||
final Predicate<PaperCard> myFilter = applyFormatFilter(QuestUtilCards.RARE_PREDICATE);
|
||||
|
||||
final List<PaperCard> newCards = Aggregates.random(Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), myFilter), n);
|
||||
this.addAllCards(newCards);
|
||||
return newCards;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup new game card pool.
|
||||
*
|
||||
* @param filter
|
||||
* the filter
|
||||
* @param idxDifficulty
|
||||
* the idx difficulty
|
||||
* @param userPrefs
|
||||
* user preferences
|
||||
*/
|
||||
public void setupNewGameCardPool(final Predicate<PaperCard> filter, final int idxDifficulty, final StartingPoolPreferences userPrefs) {
|
||||
final int nC = this.qpref.getPrefInt(DifficultyPrefs.STARTING_COMMONS, idxDifficulty);
|
||||
final int nU = this.qpref.getPrefInt(DifficultyPrefs.STARTING_UNCOMMONS, idxDifficulty);
|
||||
final int nR = this.qpref.getPrefInt(DifficultyPrefs.STARTING_RARES, idxDifficulty);
|
||||
|
||||
this.addAllCards(BoosterUtils.getQuestStarterDeck(filter, nC, nU, nR, userPrefs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Buy card.
|
||||
*
|
||||
* @param card
|
||||
* the card
|
||||
* @param qty
|
||||
* quantity
|
||||
* @param value
|
||||
* the value
|
||||
*/
|
||||
public void buyCard(final PaperCard card, int qty, final int value) {
|
||||
int totalCost = qty * value;
|
||||
if (this.qa.getCredits() >= totalCost) {
|
||||
this.qa.setCredits(this.qa.getCredits() - totalCost);
|
||||
this.qa.getShopList().remove(card, qty);
|
||||
this.addSingleCard(card, qty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Buy booster.
|
||||
*
|
||||
* @param booster
|
||||
* the booster
|
||||
* @param value
|
||||
* the value
|
||||
*/
|
||||
public void buyPack(final SealedProduct booster, final int value) {
|
||||
if (this.qa.getCredits() >= value) {
|
||||
this.qa.setCredits(this.qa.getCredits() - value);
|
||||
this.qa.getShopList().remove(booster);
|
||||
this.addAllCards(booster.getCards());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Buy precon deck.
|
||||
*
|
||||
* @param precon
|
||||
* the precon
|
||||
* @param value
|
||||
* the value
|
||||
*/
|
||||
public void buyPreconDeck(final PreconDeck precon, final int value) {
|
||||
if (this.qa.getCredits() >= value) {
|
||||
this.qa.setCredits(this.qa.getCredits() - value);
|
||||
this.qa.getShopList().remove(precon);
|
||||
this.addDeck(precon.getDeck());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import an existing deck.
|
||||
*
|
||||
* @param fromDeck
|
||||
* Deck, deck to import
|
||||
*/
|
||||
void addDeck(final Deck fromDeck) {
|
||||
if (fromDeck == null) {
|
||||
return;
|
||||
}
|
||||
this.qc.getMyDecks().add(fromDeck);
|
||||
this.addAllCards(fromDeck.getMain().toFlatList());
|
||||
if (fromDeck.has(DeckSection.Sideboard)) {
|
||||
this.addAllCards(fromDeck.get(DeckSection.Sideboard).toFlatList());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sell card.
|
||||
*
|
||||
* @param card
|
||||
* the card
|
||||
* @param qty
|
||||
* quantity
|
||||
* @param pricePerCard
|
||||
* the price per card
|
||||
*/
|
||||
public void sellCard(final PaperCard card, int qty, final int pricePerCard) {
|
||||
this.sellCard(card, qty, pricePerCard, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* lose card.
|
||||
*
|
||||
* @param card
|
||||
* the card
|
||||
* @param qty
|
||||
* quantity
|
||||
*/
|
||||
public void loseCards(final List<PaperCard> cards) {
|
||||
for(PaperCard pc: cards)
|
||||
this.sellCard(pc, 1, 0, this.qc.getAssets().getItemLevel(QuestItemType.CASH_STAKES) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sell card.
|
||||
*
|
||||
* @param card
|
||||
* the card
|
||||
* @param price
|
||||
* the price
|
||||
* @param addToShop
|
||||
* true if this card should be added to the shop, false otherwise
|
||||
*/
|
||||
private void sellCard(final PaperCard card, int qty, final int pricePerCard, final boolean addToShop) {
|
||||
if (pricePerCard > 0) {
|
||||
this.qa.setCredits(this.qa.getCredits() + (qty * pricePerCard));
|
||||
}
|
||||
this.qa.getCardPool().remove(card, qty);
|
||||
if (addToShop) {
|
||||
this.qa.getShopList().add(card, qty);
|
||||
}
|
||||
|
||||
// remove card being sold from all decks
|
||||
final int leftInPool = this.qa.getCardPool().count(card);
|
||||
// remove sold cards from all decks:
|
||||
for (final Deck deck : this.qc.getMyDecks()) {
|
||||
int cntInMain = deck.getMain().count(card);
|
||||
int cntInSb = deck.has(DeckSection.Sideboard) ? deck.get(DeckSection.Sideboard).count(card) : 0;
|
||||
int nToRemoveFromThisDeck = cntInMain + cntInSb - leftInPool;
|
||||
if (nToRemoveFromThisDeck <= 0) {
|
||||
continue; // this is not the deck you are looking for
|
||||
}
|
||||
|
||||
int nToRemoveFromSb = Math.min(cntInSb, nToRemoveFromThisDeck);
|
||||
if (nToRemoveFromSb > 0) {
|
||||
deck.get(DeckSection.Sideboard).remove(card, nToRemoveFromSb);
|
||||
nToRemoveFromThisDeck -= nToRemoveFromSb;
|
||||
if (0 >= nToRemoveFromThisDeck) {
|
||||
continue; // done here
|
||||
}
|
||||
}
|
||||
|
||||
deck.getMain().remove(card, nToRemoveFromThisDeck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear shop list.
|
||||
*/
|
||||
public void clearShopList() {
|
||||
if (null != this.qa.getShopList()) {
|
||||
this.qa.getShopList().clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sell mutliplier.
|
||||
*
|
||||
* @return the sell mutliplier
|
||||
*/
|
||||
public double getSellMultiplier() {
|
||||
double multi = 0.20 + (0.001 * this.qc.getAchievements().getWin());
|
||||
if (multi > 0.6) {
|
||||
multi = 0.6;
|
||||
}
|
||||
|
||||
final int lvlEstates = this.qc.getMode() == QuestMode.Fantasy ? this.qa.getItemLevel(QuestItemType.ESTATES) : 0;
|
||||
switch (lvlEstates) {
|
||||
case 1:
|
||||
multi += 0.01;
|
||||
break;
|
||||
case 2:
|
||||
multi += 0.0175;
|
||||
break;
|
||||
case 3:
|
||||
multi += 0.025;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return multi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sell price limit.
|
||||
*
|
||||
* @return the sell price limit
|
||||
*/
|
||||
public int getSellPriceLimit() {
|
||||
return this.qc.getAchievements().getWin() <= 50 ? 1000 : Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate cards in shop.
|
||||
*/
|
||||
private final GameFormat.Collection formats = FModel.getFormats();
|
||||
private final Predicate<CardEdition> filterExt = this.formats.getExtended().editionLegalPredicate;
|
||||
|
||||
/** The filter t2booster. */
|
||||
private final Predicate<CardEdition> filterT2booster = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER,
|
||||
this.formats.getStandard().editionLegalPredicate);
|
||||
|
||||
/** The filter ext but t2. */
|
||||
private final Predicate<CardEdition> filterExtButT2 = Predicates.and(
|
||||
CardEdition.Predicates.CAN_MAKE_BOOSTER,
|
||||
Predicates.and(this.filterExt, this.formats.getStandard().editionLegalPredicate));
|
||||
|
||||
/** The filter not ext. */
|
||||
private final Predicate<CardEdition> filterNotExt = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER,
|
||||
Predicates.not(this.filterExt));
|
||||
|
||||
/**
|
||||
* Helper predicate for shops: is legal in quest format.
|
||||
*
|
||||
* @param qFormat
|
||||
* the quest format
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate<CardEdition> isLegalInQuestFormat(final GameFormatQuest qFormat) {
|
||||
return GameFormatQuest.Predicates.isLegalInFormatQuest(qFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate boosters in shop.
|
||||
*
|
||||
* @param count
|
||||
* the count
|
||||
*/
|
||||
private void generateBoostersInShop(final int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
final int rollD100 = MyRandom.getRandom().nextInt(100);
|
||||
Predicate<CardEdition> filter = rollD100 < 40 ? this.filterT2booster
|
||||
: (rollD100 < 75 ? this.filterExtButT2 : this.filterNotExt);
|
||||
if (qc.getFormat() != null) {
|
||||
filter = Predicates.and(CardEdition.Predicates.CAN_MAKE_BOOSTER, isLegalInQuestFormat(qc.getFormat()));
|
||||
}
|
||||
Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), filter);
|
||||
this.qa.getShopList().add(BoosterPack.FN_FROM_SET.apply(Aggregates.random(rightEditions)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate precons in shop.
|
||||
*
|
||||
* @param count
|
||||
* the count
|
||||
*/
|
||||
private void generateTournamentsInShop(final int count) {
|
||||
Predicate<CardEdition> formatFilter = CardEdition.Predicates.HAS_TOURNAMENT_PACK;
|
||||
if (qc.getFormat() != null) {
|
||||
formatFilter = Predicates.and(formatFilter, isLegalInQuestFormat(qc.getFormat()));
|
||||
}
|
||||
Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), formatFilter);
|
||||
this.qa.getShopList().addAllFlat(Aggregates.random(Iterables.transform(rightEditions, TournamentPack.FN_FROM_SET), count));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate precons in shop.
|
||||
*
|
||||
* @param count
|
||||
* the count
|
||||
*/
|
||||
private void generateFatPacksInShop(final int count) {
|
||||
Predicate<CardEdition> formatFilter = CardEdition.Predicates.HAS_FAT_PACK;
|
||||
if (qc.getFormat() != null) {
|
||||
formatFilter = Predicates.and(formatFilter, isLegalInQuestFormat(qc.getFormat()));
|
||||
}
|
||||
Iterable<CardEdition> rightEditions = Iterables.filter(FModel.getMagicDb().getEditions(), formatFilter);
|
||||
this.qa.getShopList().addAllFlat(Aggregates.random(Iterables.transform(rightEditions, FatPack.FN_FROM_SET), count));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate precons in shop.
|
||||
*
|
||||
* @param count
|
||||
* the count
|
||||
*/
|
||||
private void generatePreconsInShop(final int count) {
|
||||
final List<PreconDeck> meetRequirements = new ArrayList<PreconDeck>();
|
||||
for (final PreconDeck deck : QuestController.getPrecons()) {
|
||||
if (QuestController.getPreconDeals(deck).meetsRequiremnts(this.qc.getAchievements())
|
||||
&& (null == qc.getFormat() || qc.getFormat().isSetLegal(deck.getEdition()))) {
|
||||
meetRequirements.add(deck);
|
||||
}
|
||||
}
|
||||
this.qa.getShopList().addAllFlat(Aggregates.random(meetRequirements, count));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private SealedProduct.Template getShopBoosterTemplate() {
|
||||
return new SealedProduct.Template(Lists.newArrayList(
|
||||
Pair.of(BoosterSlots.COMMON, this.qpref.getPrefInt(QPref.SHOP_SINGLES_COMMON)),
|
||||
Pair.of(BoosterSlots.UNCOMMON, this.qpref.getPrefInt(QPref.SHOP_SINGLES_UNCOMMON)),
|
||||
Pair.of(BoosterSlots.RARE_MYTHIC, this.qpref.getPrefInt(QPref.SHOP_SINGLES_RARE))
|
||||
));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private SealedProduct.Template getBoosterTemplate() {
|
||||
return new SealedProduct.Template(Lists.newArrayList(
|
||||
Pair.of(BoosterSlots.COMMON, this.qpref.getPrefInt(QPref.BOOSTER_COMMONS)),
|
||||
Pair.of(BoosterSlots.UNCOMMON, this.qpref.getPrefInt(QPref.BOOSTER_UNCOMMONS)),
|
||||
Pair.of(BoosterSlots.RARE_MYTHIC, this.qpref.getPrefInt(QPref.BOOSTER_RARES))
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate cards in shop.
|
||||
*/
|
||||
private void generateCardsInShop() {
|
||||
// Preferences
|
||||
final int startPacks = this.qpref.getPrefInt(QPref.SHOP_STARTING_PACKS);
|
||||
final int winsForPack = this.qpref.getPrefInt(QPref.SHOP_WINS_FOR_ADDITIONAL_PACK);
|
||||
final int maxPacks = this.qpref.getPrefInt(QPref.SHOP_MAX_PACKS);
|
||||
|
||||
int level = this.qc.getAchievements().getLevel();
|
||||
final int levelPacks = level > 0 ? startPacks / level : startPacks;
|
||||
final int winPacks = this.qc.getAchievements().getWin() / winsForPack;
|
||||
final int totalPacks = Math.min(levelPacks + winPacks, maxPacks);
|
||||
|
||||
|
||||
SealedProduct.Template tpl = getShopBoosterTemplate();
|
||||
UnOpenedProduct unopened = qc.getFormat() == null ? new UnOpenedProduct(tpl) : new UnOpenedProduct(tpl, qc.getFormat().getFilterPrinted());
|
||||
|
||||
for (int i = 0; i < totalPacks; i++) {
|
||||
this.qa.getShopList().addAllFlat(unopened.get());
|
||||
}
|
||||
|
||||
this.generateBoostersInShop(totalPacks);
|
||||
this.generatePreconsInShop(totalPacks);
|
||||
this.generateTournamentsInShop(totalPacks);
|
||||
this.generateFatPacksInShop(totalPacks);
|
||||
int numberSnowLands = 5;
|
||||
if (qc.getFormat() != null && !qc.getFormat().hasSnowLands()) {
|
||||
numberSnowLands = 0;
|
||||
}
|
||||
this.qa.getShopList().addAll(QuestUtilCards.generateBasicLands(10, numberSnowLands, qc.getFormat()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cardpool.
|
||||
*
|
||||
* @return the cardpool
|
||||
*/
|
||||
public ItemPool<PaperCard> getCardpool() {
|
||||
return this.qa.getCardPool();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the shop list.
|
||||
*
|
||||
* @return the shop list
|
||||
*/
|
||||
public ItemPool<InventoryItem> getShopList() {
|
||||
if (this.qa.getShopList().isEmpty()) {
|
||||
this.generateCardsInShop();
|
||||
}
|
||||
return this.qa.getShopList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the new cards.
|
||||
*
|
||||
* @return the new cards
|
||||
*/
|
||||
public ItemPool<InventoryItem> getNewCards() {
|
||||
return this.qa.getNewCardList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset new list.
|
||||
*/
|
||||
public void resetNewList() {
|
||||
this.qa.getNewCardList().clear();
|
||||
}
|
||||
|
||||
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnNewCompare() {
|
||||
return this.fnNewCompare;
|
||||
}
|
||||
|
||||
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnNewGet() {
|
||||
return this.fnNewGet;
|
||||
}
|
||||
|
||||
// These functions provide a way to sort and compare cards in a table
|
||||
// according to their new-ness
|
||||
// It might be a good idea to store them in a base class for both quest-mode
|
||||
// deck editors
|
||||
// Maybe we should consider doing so later
|
||||
/** The fn new compare. */
|
||||
private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnNewCompare =
|
||||
new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
|
||||
@Override
|
||||
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
|
||||
return QuestUtilCards.this.qa.getNewCardList().contains(from.getKey()) ? Integer.valueOf(1) : Integer
|
||||
.valueOf(0);
|
||||
}
|
||||
};
|
||||
|
||||
/** The fn new get. */
|
||||
private final Function<Entry<? extends InventoryItem, Integer>, Object> fnNewGet =
|
||||
new Function<Entry<? extends InventoryItem, Integer>, Object>() {
|
||||
@Override
|
||||
public Object apply(final Entry<? extends InventoryItem, Integer> from) {
|
||||
return QuestUtilCards.this.qa.getNewCardList().contains(from.getKey()) ? "NEW" : "";
|
||||
}
|
||||
};
|
||||
|
||||
public Function<Entry<InventoryItem, Integer>, Comparable<?>> getFnOwnedCompare() {
|
||||
return this.fnOwnedCompare;
|
||||
}
|
||||
|
||||
public Function<Entry<? extends InventoryItem, Integer>, Object> getFnOwnedGet() {
|
||||
return this.fnOwnedGet;
|
||||
}
|
||||
|
||||
public int getCompletionPercent(String edition) {
|
||||
// get all cards in the specified edition
|
||||
Predicate<PaperCard> filter = IPaperCard.Predicates.printedInSet(edition);
|
||||
Iterable<PaperCard> editionCards = Iterables.filter(FModel.getMagicDb().getCommonCards().getAllCards(), filter);
|
||||
|
||||
ItemPool<PaperCard> ownedCards = qa.getCardPool();
|
||||
// 100% means at least one of every basic land and at least 4 of every other card in the set
|
||||
int completeCards = 0;
|
||||
int numOwnedCards = 0;
|
||||
for (PaperCard card : editionCards) {
|
||||
final int target = CardRarity.BasicLand == card.getRarity() ? 1 : 4;
|
||||
|
||||
completeCards += target;
|
||||
numOwnedCards += Math.min(target, ownedCards.count(card));
|
||||
}
|
||||
|
||||
return (numOwnedCards * 100) / completeCards;
|
||||
}
|
||||
|
||||
// These functions provide a way to sort and compare items in the spell shop according to how many are already owned
|
||||
private final Function<Entry<InventoryItem, Integer>, Comparable<?>> fnOwnedCompare =
|
||||
new Function<Entry<InventoryItem, Integer>, Comparable<?>>() {
|
||||
@Override
|
||||
public Comparable<?> apply(final Entry<InventoryItem, Integer> from) {
|
||||
InventoryItem i = from.getKey();
|
||||
if (i instanceof PaperCard) {
|
||||
return QuestUtilCards.this.qa.getCardPool().count((PaperCard) i);
|
||||
} else if (i instanceof PreconDeck) {
|
||||
PreconDeck pDeck = (PreconDeck) i;
|
||||
return FModel.getQuest().getMyDecks().contains(pDeck.getName()) ? -1 : -2;
|
||||
} else if (i instanceof SealedProduct) {
|
||||
SealedProduct oPack = (SealedProduct) i;
|
||||
return getCompletionPercent(oPack.getEdition()) - 103;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
private final Function<Entry<? extends InventoryItem, Integer>, Object> fnOwnedGet =
|
||||
new Function<Entry<? extends InventoryItem, Integer>, Object>() {
|
||||
@Override
|
||||
public Object apply(final Entry<? extends InventoryItem, Integer> from) {
|
||||
InventoryItem i = from.getKey();
|
||||
if (i instanceof PaperCard) {
|
||||
return QuestUtilCards.this.qa.getCardPool().count((PaperCard) i);
|
||||
} else if (i instanceof PreconDeck) {
|
||||
PreconDeck pDeck = (PreconDeck) i;
|
||||
return FModel.getQuest().getMyDecks().contains(pDeck.getName()) ? "YES" : "NO";
|
||||
} else if (i instanceof SealedProduct) {
|
||||
SealedProduct oPack = (SealedProduct) i;
|
||||
return String.format("%d%%", getCompletionPercent(oPack.getEdition()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
202
forge-m-base/src/forge/quest/QuestUtilUnlockSets.java
Normal file
202
forge-m-base/src/forge/quest/QuestUtilUnlockSets.java
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Nate
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.UnOpenedProduct;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.FDeckViewer;
|
||||
import forge.item.PaperCard;
|
||||
import forge.item.SealedProduct;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.io.ReadPriceList;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.GuiChoose;
|
||||
import forge.util.storage.IStorage;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This is a helper class for unlocking new sets during a format-limited
|
||||
* quest.
|
||||
*
|
||||
*/
|
||||
public class QuestUtilUnlockSets {
|
||||
private static int UNLOCK_COST = 4000;
|
||||
|
||||
/**
|
||||
* Consider unlocking a new expansion in limited quest format.
|
||||
* @param qData the QuestController for the current quest
|
||||
* @param freeUnlock this unlock is free (e.g., a challenge reward), NOT IMPLEMENTED YET
|
||||
* @param presetChoices List<CardEdition> a pregenerated list of options, NOT IMPLEMENTED YET
|
||||
* @return CardEdition, the unlocked edition if any.
|
||||
*/
|
||||
public static ImmutablePair<CardEdition, Integer> chooseSetToUnlock(final QuestController qData, final boolean freeUnlock,
|
||||
List<CardEdition> presetChoices) {
|
||||
|
||||
if (qData.getFormat() == null || !qData.getFormat().canUnlockSets()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ReadPriceList prices = new ReadPriceList();
|
||||
final Map<String, Integer> mapPrices = prices.getPriceList();
|
||||
final List<ImmutablePair<CardEdition, Integer>> setPrices = new ArrayList<ImmutablePair<CardEdition, Integer>>();
|
||||
|
||||
for (CardEdition ed : getUnlockableEditions(qData)) {
|
||||
int price = UNLOCK_COST;
|
||||
if (mapPrices.containsKey(ed.getName() + " Booster Pack")) {
|
||||
price = Math.max(new Double(30 * Math.pow(Math.sqrt(mapPrices.get(ed.getName()
|
||||
+ " Booster Pack")), 1.70)).intValue(), UNLOCK_COST);
|
||||
}
|
||||
setPrices.add(ImmutablePair.of(ed, price));
|
||||
}
|
||||
|
||||
final String setPrompt = "You have " + qData.getAssets().getCredits() + " credits. Unlock:";
|
||||
List<String> options = new ArrayList<String>();
|
||||
for (ImmutablePair<CardEdition, Integer> ee : setPrices) {
|
||||
options.add(String.format("%s [PRICE: %d credits]", ee.left.getName(), ee.right));
|
||||
}
|
||||
|
||||
int index = options.indexOf(GuiChoose.oneOrNone(setPrompt, options));
|
||||
if (index < 0 || index >= options.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ImmutablePair<CardEdition, Integer> toBuy = setPrices.get(index);
|
||||
|
||||
int price = toBuy.right;
|
||||
CardEdition choosenEdition = toBuy.left;
|
||||
|
||||
if (qData.getAssets().getCredits() < price) {
|
||||
FOptionPane.showMessageDialog("Unfortunately, you cannot afford that set yet.\n"
|
||||
+ "To unlock " + choosenEdition.getName() + ", you need " + price + " credits.\n"
|
||||
+ "You have only " + qData.getAssets().getCredits() + " credits.",
|
||||
"Failed to unlock " + choosenEdition.getName(),
|
||||
null);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!FOptionPane.showConfirmDialog(
|
||||
"Unlocking " + choosenEdition.getName() + " will cost you " + price + " credits.\n"
|
||||
+ "You have " + qData.getAssets().getCredits() + " credits.\n\n"
|
||||
+ "Are you sure you want to unlock " + choosenEdition.getName() + "?",
|
||||
"Confirm Unlocking " + choosenEdition.getName())) {
|
||||
return null;
|
||||
}
|
||||
return toBuy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for unlockSet().
|
||||
*
|
||||
* @return unmodifiable list, assorted sets that are not currently in the format.
|
||||
*/
|
||||
private static final List<CardEdition> emptyEditions = ImmutableList.<CardEdition>of();
|
||||
private static final EnumSet<CardEdition.Type> unlockableSetTypes =
|
||||
EnumSet.of(CardEdition.Type.CORE, CardEdition.Type.EXPANSION, CardEdition.Type.REPRINT, CardEdition.Type.STARTER);
|
||||
|
||||
private static List<CardEdition> getUnlockableEditions(final QuestController qData) {
|
||||
if (qData.getFormat() == null || !qData.getFormat().canUnlockSets()) {
|
||||
return emptyEditions;
|
||||
}
|
||||
|
||||
if (qData.getUnlocksTokens() < 1) { // Should never happen if we made it this far but better safe than sorry...
|
||||
throw new RuntimeException("BUG? Could not find unlockable sets even though we should.");
|
||||
}
|
||||
List<CardEdition> options = new ArrayList<CardEdition>();
|
||||
|
||||
// Sort current sets by date
|
||||
List<CardEdition> allowedSets = Lists.newArrayList(Iterables.transform(qData.getFormat().getAllowedSetCodes(), FModel.getMagicDb().getEditions().FN_EDITION_BY_CODE));
|
||||
Collections.sort(allowedSets);
|
||||
|
||||
// Sort unlockable sets by date
|
||||
List<CardEdition> excludedSets = Lists.newArrayList(Iterables.transform(qData.getFormat().getLockedSets(), FModel.getMagicDb().getEditions().FN_EDITION_BY_CODE));
|
||||
Collections.sort(excludedSets);
|
||||
|
||||
// get a number of sets between an excluded and any included set
|
||||
List<ImmutablePair<CardEdition, Long>> excludedWithDistances = new ArrayList<ImmutablePair<CardEdition, Long>>();
|
||||
for (CardEdition ex : excludedSets) {
|
||||
if (!unlockableSetTypes.contains(ex.getType())) // don't add non-traditional sets
|
||||
continue;
|
||||
long distance = Long.MAX_VALUE;
|
||||
for (CardEdition in : allowedSets) {
|
||||
long d = (Math.abs(ex.getDate().getTime() - in.getDate().getTime()));
|
||||
if (d < distance) {
|
||||
distance = d;
|
||||
}
|
||||
}
|
||||
excludedWithDistances.add(ImmutablePair.of(ex, distance));
|
||||
}
|
||||
|
||||
// sort by distance, then by code desc
|
||||
Collections.sort(excludedWithDistances, new Comparator<ImmutablePair<CardEdition, Long>>() {
|
||||
@Override
|
||||
public int compare(ImmutablePair<CardEdition, Long> o1, ImmutablePair<CardEdition, Long> o2) {
|
||||
long delta = o2.right - o1.right;
|
||||
return delta < 0 ? -1 : delta == 0 ? 0 : 1;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
for (ImmutablePair<CardEdition, Long> set : excludedWithDistances) {
|
||||
options.add(set.left);
|
||||
// System.out.println("Padded with: " + fillers.get(i).getName());
|
||||
}
|
||||
Collections.reverse(options);
|
||||
|
||||
return options.subList(0, Math.min(options.size(), Math.min(8, 2 + ((qData.getAchievements().getWin()) / 50))));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Unlock a set and get some free cards, if a tournament pack or boosters are available.
|
||||
* @param qData the quest controller
|
||||
* @param unlockedSet the edition to unlock
|
||||
*/
|
||||
public static void doUnlock(QuestController qData, final CardEdition unlockedSet) {
|
||||
|
||||
IStorage<SealedProduct.Template> starters = FModel.getMagicDb().getTournamentPacks();
|
||||
IStorage<SealedProduct.Template> boosters = FModel.getMagicDb().getBoosters();
|
||||
qData.getFormat().unlockSet(unlockedSet.getCode());
|
||||
|
||||
List<PaperCard> cardsWon = new ArrayList<PaperCard>();
|
||||
|
||||
if (starters.contains(unlockedSet.getCode())) {
|
||||
UnOpenedProduct starter = new UnOpenedProduct(starters.get(unlockedSet.getCode()));
|
||||
cardsWon.addAll(starter.get());
|
||||
}
|
||||
else if (boosters.contains(unlockedSet.getCode())) {
|
||||
UnOpenedProduct booster = new UnOpenedProduct(boosters.get(unlockedSet.getCode()));
|
||||
cardsWon.addAll(booster.get());
|
||||
cardsWon.addAll(booster.get());
|
||||
cardsWon.addAll(booster.get());
|
||||
}
|
||||
|
||||
qData.getCards().addAllCards(cardsWon);
|
||||
Deck deck = new Deck(unlockedSet.getName() + " - You get the following bonus cards:");
|
||||
deck.getMain().addAllFlat(cardsWon);
|
||||
FDeckViewer.show(deck);
|
||||
qData.save();
|
||||
}
|
||||
}
|
||||
184
forge-m-base/src/forge/quest/QuestWorld.java
Normal file
184
forge-m-base/src/forge/quest/QuestWorld.java
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Nate
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import forge.quest.data.GameFormatQuest;
|
||||
import forge.util.storage.StorageReaderFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This function holds the "world info" for the current quest.
|
||||
*
|
||||
*/
|
||||
public class QuestWorld implements Comparable<QuestWorld>{
|
||||
private final String name;
|
||||
private final String dir;
|
||||
private final GameFormatQuest format;
|
||||
|
||||
/**
|
||||
* Instantiate a new quest world.
|
||||
* @param useIdx int, the quest world internal identifier
|
||||
* @param useName String, the display name for the world
|
||||
* @param useDir String, the basedir that contains the duels and challenges for the quest world
|
||||
* @param useFormat GameFormatQuest that contains the initial format for the world
|
||||
*/
|
||||
public QuestWorld(final String useName, final String useDir, final GameFormatQuest useFormat) {
|
||||
name = useName;
|
||||
dir = useDir;
|
||||
format = useFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* The quest world display name.
|
||||
* @return String, the display name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The quest world duels directory.
|
||||
* @return String, the duels directory
|
||||
*/
|
||||
public String getDuelsDir() {
|
||||
return dir == null ? null : dir + "/duels";
|
||||
}
|
||||
|
||||
/**
|
||||
* The quest world challenges directory.
|
||||
* @return String, the challenges directory
|
||||
*/
|
||||
public String getChallengesDir() {
|
||||
return dir == null ? null : dir + "/challenges";
|
||||
}
|
||||
|
||||
/**
|
||||
* The quest world format if specified.
|
||||
* @return GameFormatQuest, the format
|
||||
*/
|
||||
public GameFormatQuest getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* toString.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
@Override
|
||||
public final String toString() {
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* FN_GET_NAME for reader.
|
||||
*/
|
||||
public static final Function<QuestWorld, String> FN_GET_NAME = new Function<QuestWorld, String>() {
|
||||
|
||||
@Override
|
||||
public String apply(QuestWorld arg1) {
|
||||
return arg1.getName();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for reading world definitions.
|
||||
*/
|
||||
public static class Reader extends StorageReaderFile<QuestWorld> {
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param file0
|
||||
* @param keySelector0
|
||||
*/
|
||||
public Reader(String file0) {
|
||||
super(file0, QuestWorld.FN_GET_NAME);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.util.StorageReaderFile#read(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
protected QuestWorld read(String line, int i) {
|
||||
String useName = null;
|
||||
String useDir = null;
|
||||
GameFormatQuest useFormat = null;
|
||||
|
||||
final List<String> sets = new ArrayList<String>();
|
||||
final List<String> bannedCards = new ArrayList<String>(); // if both empty, no format
|
||||
|
||||
// This is what you need to use here =>
|
||||
// FileSection.parse(line, ":", "|");
|
||||
|
||||
final String[] sParts = line.trim().split("\\|");
|
||||
|
||||
for (final String sPart : sParts) {
|
||||
|
||||
final String[] kv = sPart.split(":", 2);
|
||||
final String key = kv[0].toLowerCase();
|
||||
if ("name".equals(key)) {
|
||||
useName = kv[1];
|
||||
} else if ("dir".equals(key)) {
|
||||
useDir = kv[1];
|
||||
} else if ("sets".equals(key)) {
|
||||
sets.addAll(Arrays.asList(kv[1].split(", ")));
|
||||
} else if ("banned".equals(key)) {
|
||||
bannedCards.addAll(Arrays.asList(kv[1].split("; ")));
|
||||
}
|
||||
}
|
||||
|
||||
if (useName == null) {
|
||||
throw new RuntimeException("A Quest World must have a name! Check worlds.txt file");
|
||||
}
|
||||
|
||||
if (!sets.isEmpty() || !bannedCards.isEmpty()) {
|
||||
useFormat = new GameFormatQuest(useName, sets, bannedCards);
|
||||
}
|
||||
|
||||
// System.out.println("Creating quest world " + useName + " (index " + useIdx + ", dir: " + useDir);
|
||||
// if (useFormat != null) { System.out.println("SETS: " + sets + "\nBANNED: " + bannedCards); }
|
||||
|
||||
return new QuestWorld(useName, useDir, useFormat);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(QuestWorld other) {
|
||||
if (null == other) {
|
||||
return 1;
|
||||
}
|
||||
if (name == other.name) {
|
||||
return 0;
|
||||
}
|
||||
if (null == name) {
|
||||
return -1;
|
||||
}
|
||||
return name.compareTo(other.name);
|
||||
}
|
||||
}
|
||||
88
forge-m-base/src/forge/quest/SellRules.java
Normal file
88
forge-m-base/src/forge/quest/SellRules.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
import forge.quest.data.QuestAchievements;
|
||||
import forge.util.FileSection;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public class SellRules {
|
||||
|
||||
private int minWins = 0;
|
||||
private int cost = 250;
|
||||
private int minDifficulty = 0;
|
||||
private int maxDifficulty = 5;
|
||||
|
||||
/**
|
||||
* Instantiates a new sell rules.
|
||||
*
|
||||
* @param questShop the quest shop
|
||||
*/
|
||||
public SellRules(List<String> questShop) {
|
||||
if (null == questShop || questShop.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FileSection section = FileSection.parse(questShop, "=");
|
||||
minWins = section.getInt("WinsToUnlock");
|
||||
cost = section.getInt("Credits", 250);
|
||||
maxDifficulty = section.getInt("MaxDifficulty", 5);
|
||||
minDifficulty = section.getInt("MinDifficulty", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Meets requiremnts.
|
||||
*
|
||||
* @param quest the quest
|
||||
* @return true, if successful
|
||||
*/
|
||||
public boolean meetsRequiremnts(QuestAchievements quest) {
|
||||
if (quest.getWin() < minWins) {
|
||||
return false;
|
||||
}
|
||||
if (quest.getDifficulty() < minDifficulty || quest.getDifficulty() > maxDifficulty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cost.
|
||||
*
|
||||
* @return the cost
|
||||
*/
|
||||
public final int getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minWins.
|
||||
*
|
||||
* @return the minWins
|
||||
*/
|
||||
public final int getMinWins() {
|
||||
return minWins;
|
||||
}
|
||||
|
||||
}
|
||||
61
forge-m-base/src/forge/quest/StartingPoolPreferences.java
Normal file
61
forge-m-base/src/forge/quest/StartingPoolPreferences.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Nate
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest;
|
||||
|
||||
/**
|
||||
* This class is used to store the Quest starting pool preferences.
|
||||
* (It could be expanded to store other Quest starting preferences as well,
|
||||
* in order to reduce the number of parameters that need to be passed to
|
||||
* QuestController.newGame from CSubmenuQuestData)
|
||||
*
|
||||
*/
|
||||
public final class StartingPoolPreferences {
|
||||
|
||||
private final boolean randomPool;
|
||||
private final byte preferredColor;
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
* @param random
|
||||
* true = use completely random pool without filter restrictions
|
||||
* (Note that this does NOT bypass card rarity restrictions!)
|
||||
* @param preference
|
||||
* preferred color/COLORLESS (ALL_COLORS = no preference)
|
||||
*/
|
||||
public StartingPoolPreferences(final boolean random, final byte preference) {
|
||||
randomPool = random;
|
||||
preferredColor = preference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the starting pool completely random?
|
||||
* @return boolean, true if the starting pool is completely random (except for rarity)
|
||||
*/
|
||||
public boolean useRandomPool() {
|
||||
return randomPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the preferred starting pool color.
|
||||
* Return ALL_COLORS if no preference set.
|
||||
* @return MagicColor
|
||||
*/
|
||||
public byte getPreferredColor() {
|
||||
return preferredColor;
|
||||
}
|
||||
}
|
||||
25
forge-m-base/src/forge/quest/StartingPoolType.java
Normal file
25
forge-m-base/src/forge/quest/StartingPoolType.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package forge.quest;
|
||||
|
||||
public enum StartingPoolType {
|
||||
Complete("Unrestricted"),
|
||||
Rotating("Sanctioned format"),
|
||||
CustomFormat("Custom format"),
|
||||
Precon("Event or starter deck"),
|
||||
SealedDeck("My sealed deck"),
|
||||
DraftDeck("My draft deck"),
|
||||
Cube("Predefined cube");
|
||||
|
||||
private final String caption;
|
||||
|
||||
private StartingPoolType(String caption0) {
|
||||
caption = caption0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Enum#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return caption;
|
||||
}
|
||||
}
|
||||
89
forge-m-base/src/forge/quest/bazaar/IQuestBazaarItem.java
Normal file
89
forge-m-base/src/forge/quest/bazaar/IQuestBazaarItem.java
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import forge.assets.FImage;
|
||||
import forge.quest.data.QuestAssets;
|
||||
|
||||
/**
|
||||
* This interface defines a thing that can be sold at the Bazaar.
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: IQuestBazaarItem.java 23229 2013-09-16 08:18:19Z drdev $
|
||||
*/
|
||||
public interface IQuestBazaarItem extends Comparable<Object> {
|
||||
/**
|
||||
* <p>
|
||||
* getPurchaseName.
|
||||
* </p>
|
||||
*
|
||||
* @return The Name of the item
|
||||
*/
|
||||
String getPurchaseName();
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPurchaseDescription.
|
||||
* </p>
|
||||
*
|
||||
* @return an HTML formatted item description
|
||||
*/
|
||||
String getPurchaseDescription(QuestAssets qA);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getIcon.
|
||||
* </p>
|
||||
*
|
||||
* @return the icon that is displayed in the bazaar
|
||||
*/
|
||||
FImage getIcon(QuestAssets qA);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPrice.
|
||||
* </p>
|
||||
*
|
||||
* @return the buying cost of the item in credits
|
||||
*/
|
||||
int getBuyingPrice(QuestAssets qA);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPrice.
|
||||
* </p>
|
||||
*
|
||||
* @return the selling cost of the item in credits
|
||||
*/
|
||||
int getSellingPrice(QuestAssets qA);
|
||||
|
||||
/**
|
||||
* Returns if the item is available for purchase;.
|
||||
*
|
||||
* @return <code>true</code> if the item can be displayed in a store
|
||||
* <code>false</code> if the item should not be displayed in store
|
||||
* since, for example, prerequisites are not met
|
||||
*/
|
||||
boolean isAvailableForPurchase(QuestAssets questAssets);
|
||||
|
||||
/**
|
||||
* Executed when the item is bought.
|
||||
* @param questAssets
|
||||
*/
|
||||
void onPurchase(QuestAssets questAssets);
|
||||
}
|
||||
185
forge-m-base/src/forge/quest/bazaar/QuestBazaarManager.java
Normal file
185
forge-m-base/src/forge/quest/bazaar/QuestBazaarManager.java
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
|
||||
import forge.model.FModel;
|
||||
import forge.quest.QuestController;
|
||||
import forge.quest.data.QuestAssets;
|
||||
import forge.utils.IgnoringXStream;
|
||||
import forge.utils.XmlUtil;
|
||||
|
||||
import org.w3c.dom.*;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestStallManager class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestBazaarManager.java 24769 2014-02-09 13:56:04Z Hellfish $
|
||||
*/
|
||||
public class QuestBazaarManager {
|
||||
private final File xmlFile;
|
||||
|
||||
public QuestBazaarManager(File xmlFile0) {
|
||||
xmlFile = xmlFile0;
|
||||
}
|
||||
|
||||
public void load() {
|
||||
DocumentBuilder builder;
|
||||
try {
|
||||
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final Document document = builder.parse(xmlFile);
|
||||
|
||||
XStream xs = new IgnoringXStream();
|
||||
xs.autodetectAnnotations(true);
|
||||
|
||||
NodeList xmlStalls = document.getElementsByTagName("stalls").item(0).getChildNodes();
|
||||
for (int iN = 0; iN < xmlStalls.getLength(); iN++) {
|
||||
Node n = xmlStalls.item(iN);
|
||||
if (n.getNodeType() != Node.ELEMENT_NODE) { continue; }
|
||||
|
||||
Attr att = document.createAttribute("resolves-to");
|
||||
att.setValue(QuestStallDefinition.class.getCanonicalName());
|
||||
n.getAttributes().setNamedItem(att);
|
||||
QuestStallDefinition stall = (QuestStallDefinition) xs.fromXML(XmlUtil.nodeToString(n));
|
||||
stalls.put(stall.getName(), stall);
|
||||
}
|
||||
|
||||
NodeList xmlQuestItems = document.getElementsByTagName("questItems").item(0).getChildNodes();
|
||||
for (int iN = 0; iN < xmlQuestItems.getLength(); iN++) {
|
||||
Node n = xmlQuestItems.item(iN);
|
||||
if (n.getNodeType() != Node.ELEMENT_NODE) { continue; }
|
||||
|
||||
NamedNodeMap attrs = n.getAttributes();
|
||||
String sType = attrs.getNamedItem("itemType").getTextContent();
|
||||
String name = attrs.getNamedItem("name").getTextContent();
|
||||
QuestItemType qType = QuestItemType.smartValueOf(sType);
|
||||
Attr att = document.createAttribute("resolves-to");
|
||||
att.setValue(qType.getBazaarControllerClass().getCanonicalName());
|
||||
attrs.setNamedItem(att);
|
||||
QuestItemBasic ctrl = (QuestItemBasic) xs.fromXML(XmlUtil.nodeToString(n));
|
||||
items.put(name, ctrl);
|
||||
}
|
||||
|
||||
} catch (SAXException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/** Constant <code>stalls</code>. */
|
||||
private final Map<String, QuestStallDefinition> stalls = new TreeMap<String, QuestStallDefinition>();
|
||||
/** Constant <code>items</code>. */
|
||||
private final Map<String, SortedSet<IQuestBazaarItem>> itemsOnStalls = new TreeMap<String, SortedSet<IQuestBazaarItem>>(String.CASE_INSENSITIVE_ORDER);
|
||||
private final Map<String, IQuestBazaarItem> items = new TreeMap<String, IQuestBazaarItem>();
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getStall.
|
||||
* </p>
|
||||
*
|
||||
* @param stallName
|
||||
* a {@link java.lang.String} object.
|
||||
* @return a {@link forge.quest.bazaar.QuestStallDefinition} object.
|
||||
*/
|
||||
public QuestStallDefinition getStall(final String stallName) {
|
||||
if (stalls.isEmpty()) {
|
||||
load();
|
||||
}
|
||||
|
||||
return stalls.get(stallName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all creatures and items, iterates through them,
|
||||
* and maps to appropriate merchant.
|
||||
*/
|
||||
public void buildItems(final QuestController qCtrl) {
|
||||
final Map<String, IQuestBazaarItem> itemSet = new HashMap<String, IQuestBazaarItem>();
|
||||
|
||||
for (int iSlot = 0; iSlot < QuestController.MAX_PET_SLOTS; iSlot++) {
|
||||
|
||||
for (QuestPetController pet : qCtrl.getPetsStorage().getAllPets(iSlot)) {
|
||||
//System.out.println("Pet: " + pet.getName());
|
||||
itemSet.put(pet.getName(), pet);
|
||||
}
|
||||
}
|
||||
|
||||
itemSet.putAll(items);
|
||||
|
||||
itemsOnStalls.clear();
|
||||
|
||||
for (QuestStallDefinition thisStall : stalls.values()) {
|
||||
TreeSet<IQuestBazaarItem> set = new TreeSet<IQuestBazaarItem>();
|
||||
|
||||
for (String itemName : thisStall.getItems()) {
|
||||
IQuestBazaarItem item = itemSet.get(itemName);
|
||||
//System.out.println(itemName);
|
||||
set.add(item);
|
||||
}
|
||||
itemsOnStalls.put(thisStall.getName(), set);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <i>purchasable</i> items available for a particular stall.
|
||||
*
|
||||
* @param stallName   {@link java.lang.String}
|
||||
* @return {@link java.util.List}.
|
||||
*/
|
||||
public List<IQuestBazaarItem> getItems(final QuestController qCtrl, final String stallName) {
|
||||
buildItems(qCtrl);
|
||||
|
||||
final List<IQuestBazaarItem> ret = new ArrayList<IQuestBazaarItem>();
|
||||
|
||||
QuestAssets qA = FModel.getQuest().getAssets();
|
||||
for (final IQuestBazaarItem purchasable : itemsOnStalls.get(stallName)) {
|
||||
if (purchasable.isAvailableForPurchase(qA)) {
|
||||
ret.add(purchasable);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @return
|
||||
*/
|
||||
public Set<String> getStallNames() {
|
||||
if (stalls.isEmpty()) {
|
||||
load();
|
||||
}
|
||||
return stalls.keySet();
|
||||
}
|
||||
|
||||
}
|
||||
194
forge-m-base/src/forge/quest/bazaar/QuestItemBasic.java
Normal file
194
forge-m-base/src/forge/quest/bazaar/QuestItemBasic.java
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
import forge.assets.FImage;
|
||||
import forge.quest.data.QuestAssets;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Abstract QuestItemAbstract class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestItemBasic.java 24769 2014-02-09 13:56:04Z Hellfish $
|
||||
*/
|
||||
public class QuestItemBasic implements IQuestBazaarItem {
|
||||
|
||||
@XStreamAsAttribute
|
||||
private QuestItemType itemType;
|
||||
|
||||
/**
|
||||
* Gets the item type.
|
||||
*
|
||||
* @return the item type
|
||||
*/
|
||||
public final QuestItemType getItemType() {
|
||||
return this.itemType;
|
||||
}
|
||||
|
||||
@XStreamAsAttribute
|
||||
private int maxLevel = 1;
|
||||
|
||||
@XStreamAsAttribute
|
||||
private String purchaseName = null;
|
||||
|
||||
private String description = "Read from XML";
|
||||
|
||||
@XStreamAsAttribute
|
||||
private int basePrice = 1000;
|
||||
|
||||
/**
|
||||
* Gets the base price.
|
||||
*
|
||||
* @return the base price
|
||||
*/
|
||||
protected final int getBasePrice() {
|
||||
return this.basePrice;
|
||||
}
|
||||
|
||||
@XStreamAsAttribute
|
||||
private final FImage icon = null;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for QuestItemAbstract.
|
||||
* </p>
|
||||
*
|
||||
* @param type0 the type0
|
||||
*/
|
||||
protected QuestItemBasic(final QuestItemType type0) {
|
||||
this.itemType = type0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the name shared across all item levels e.g., "Estates".
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public final String getName() {
|
||||
return this.itemType.getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the name used in purchasing the item e.g.,"Estates Training 1".
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
@Override
|
||||
public String getPurchaseName() {
|
||||
return StringUtils.isBlank(this.purchaseName) ? this.getName() : this.purchaseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be invoked when an item is bought in a shop.
|
||||
*
|
||||
* @param qA the q a
|
||||
*/
|
||||
@Override
|
||||
public void onPurchase(final QuestAssets qA) {
|
||||
final int currentLevel = qA.getItemLevel(this.itemType);
|
||||
qA.setItemLevel(this.itemType, currentLevel + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* isAvailableForPurchase.
|
||||
* </p>
|
||||
*
|
||||
* @param qA the q a
|
||||
* @return a boolean.
|
||||
*/
|
||||
@Override
|
||||
public boolean isAvailableForPurchase(final QuestAssets qA) {
|
||||
return qA.getItemLevel(this.itemType) < this.maxLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>maxLevel</code>.
|
||||
* </p>
|
||||
*
|
||||
* @return a int.
|
||||
*/
|
||||
public final int getMaxLevel() {
|
||||
return this.maxLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* isLeveledItem.
|
||||
* </p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public final boolean isLeveledItem() {
|
||||
return this.maxLevel == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPurchaseDescription.
|
||||
* </p>
|
||||
*
|
||||
* @param qA the q a
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
@Override
|
||||
public String getPurchaseDescription(final QuestAssets qA) {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FImage getIcon(QuestAssets qA) {
|
||||
return this.icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buying price.
|
||||
*
|
||||
* @param qA the q a
|
||||
* @return a int.
|
||||
*/
|
||||
@Override
|
||||
public int getBuyingPrice(final QuestAssets qA) {
|
||||
return this.basePrice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selling price.
|
||||
*
|
||||
* @param qA the q a
|
||||
* @return a int.
|
||||
*/
|
||||
@Override
|
||||
public int getSellingPrice(final QuestAssets qA) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final int compareTo(final Object o) {
|
||||
final IQuestBazaarItem q = (IQuestBazaarItem) o;
|
||||
return this.getPurchaseName().compareTo(q.getPurchaseName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import forge.quest.data.QuestAssets;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestItemAmuletOfEndurance class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestItemZeppelin.java 14797 2012-03-18 18:09:02Z Max mtg $
|
||||
*/
|
||||
public class QuestItemCharmOfVigor extends QuestItemBasic {
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for QuestItemAmuletOfEndurance.
|
||||
* </p>
|
||||
*/
|
||||
QuestItemCharmOfVigor() {
|
||||
super(QuestItemType.CHARM); // , QuestStallManager.GEAR
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final boolean isAvailableForPurchase(QuestAssets qA) {
|
||||
return super.isAvailableForPurchase(qA);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
53
forge-m-base/src/forge/quest/bazaar/QuestItemElixir.java
Normal file
53
forge-m-base/src/forge/quest/bazaar/QuestItemElixir.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import forge.quest.data.QuestAssets;
|
||||
|
||||
/**
|
||||
* This item has special coding.
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public class QuestItemElixir extends QuestItemBasic {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for QuestItemElixir.
|
||||
* </p>
|
||||
*/
|
||||
QuestItemElixir() {
|
||||
super(QuestItemType.ELIXIR_OF_LIFE); // QuestStallManager.ALCHEMIST,
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final int getBuyingPrice(QuestAssets qA) {
|
||||
int level = qA.getItemLevel(this.getItemType());
|
||||
if (level < 5) {
|
||||
return super.getBasePrice();
|
||||
} else if (level < 10) {
|
||||
return super.getBasePrice() * 2;
|
||||
} else if (level <= this.getMaxLevel()) {
|
||||
return super.getBasePrice() * 3;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
forge-m-base/src/forge/quest/bazaar/QuestItemEstates.java
Normal file
54
forge-m-base/src/forge/quest/bazaar/QuestItemEstates.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import forge.quest.data.QuestAssets;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestItemEstates class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestItemEstates.java 14797 2012-03-18 18:09:02Z Max mtg $
|
||||
*/
|
||||
public class QuestItemEstates extends QuestItemBasic {
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for QuestItemEstates.
|
||||
* </p>
|
||||
*/
|
||||
QuestItemEstates() {
|
||||
super(QuestItemType.ESTATES); // QuestStallManager.BANKER,
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final String getPurchaseDescription(QuestAssets qA) {
|
||||
return String.format(super.getPurchaseDescription(qA),
|
||||
(10 + (qA.getItemLevel(this.getItemType()) * 5)),
|
||||
(1 + (qA.getItemLevel(this.getItemType()) * 0.75)));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final int getBuyingPrice(QuestAssets qA) {
|
||||
int level = qA.getItemLevel(this.getItemType());
|
||||
return getBasePrice() * (2 + level);
|
||||
}
|
||||
}
|
||||
66
forge-m-base/src/forge/quest/bazaar/QuestItemPoundFlesh.java
Normal file
66
forge-m-base/src/forge/quest/bazaar/QuestItemPoundFlesh.java
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import forge.quest.QuestMode;
|
||||
import forge.quest.data.QuestAssets;
|
||||
|
||||
/**
|
||||
* This item has special coding.
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestItemElixir.java 13728 2012-02-01 11:13:34Z moomarc $
|
||||
*/
|
||||
public class QuestItemPoundFlesh extends QuestItemBasic {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for QuestItemElixir.
|
||||
* </p>
|
||||
*/
|
||||
QuestItemPoundFlesh() {
|
||||
super(QuestItemType.POUND_FLESH); // QuestStallManager.ALCHEMIST,
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final String getPurchaseDescription(QuestAssets qA) {
|
||||
return String.format(super.getPurchaseDescription(qA), getSellingPrice(qA));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final int getBuyingPrice(QuestAssets qA) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final int getSellingPrice(QuestAssets qA) {
|
||||
int level = qA.getItemLevel(this.getItemType());
|
||||
if (qA.getLife(QuestMode.Fantasy) < 2) {
|
||||
return 0;
|
||||
} else if (level < 5) {
|
||||
return this.getBasePrice();
|
||||
} else if (level < 10) {
|
||||
return this.getBasePrice() * 2;
|
||||
} else {
|
||||
return this.getBasePrice() * 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
129
forge-m-base/src/forge/quest/bazaar/QuestItemType.java
Normal file
129
forge-m-base/src/forge/quest/bazaar/QuestItemType.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Nate
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import forge.quest.data.QuestItemCondition;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
@XStreamAlias(value = "forge.quest.data.item.QuestItemType")
|
||||
public enum QuestItemType {
|
||||
|
||||
/** The SLEIGHT. */
|
||||
SLEIGHT("Sleight", QuestItemBasic.class, QuestItemCondition.class),
|
||||
/** The ESTATES. */
|
||||
ESTATES("Estates", QuestItemEstates.class, QuestItemCondition.class),
|
||||
/** The LUCKY_COIN. */
|
||||
LUCKY_COIN("Lucky Coin", QuestItemBasic.class, QuestItemCondition.class),
|
||||
/** The MAP. */
|
||||
MAP("Map", QuestItemBasic.class, QuestItemCondition.class),
|
||||
/** The ZEPPELIN. */
|
||||
ZEPPELIN("Zeppelin", QuestItemZeppelin.class, QuestItemCondition.class),
|
||||
/** The ELIXIR_OF_LIFE. */
|
||||
ELIXIR_OF_LIFE("Elixir of Life", QuestItemElixir.class, QuestItemCondition.class),
|
||||
/** The POUND_FLESH. */
|
||||
POUND_FLESH("Pound of Flesh", QuestItemPoundFlesh.class, QuestItemCondition.class),
|
||||
/** The AMULET. */
|
||||
CHARM("Charm of Vigor", QuestItemCharmOfVigor.class, QuestItemCondition.class),
|
||||
|
||||
CASH_STAKES("Cash Stakes", QuestItemBasic.class, QuestItemCondition.class);
|
||||
|
||||
private final String saveFileKey;
|
||||
private final Class<? extends QuestItemBasic> bazaarControllerClass;
|
||||
private final Class<? extends QuestItemCondition> modelClass;
|
||||
|
||||
private QuestItemType(final String key, final Class<? extends QuestItemBasic> controllerClass0,
|
||||
final Class<? extends QuestItemCondition> modelClass0) {
|
||||
this.saveFileKey = key;
|
||||
this.bazaarControllerClass = controllerClass0;
|
||||
this.modelClass = modelClass0;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*
|
||||
* @return the key
|
||||
*/
|
||||
public String getKey() {
|
||||
return this.saveFileKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bazaar controller class.
|
||||
*
|
||||
* @return the bazaar controller class
|
||||
*/
|
||||
public Class<? extends QuestItemBasic> getBazaarControllerClass() {
|
||||
return this.bazaarControllerClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the model class.
|
||||
*
|
||||
* @return the model class
|
||||
*/
|
||||
public Class<? extends QuestItemCondition> getModelClass() {
|
||||
return this.modelClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Smart value of.
|
||||
*
|
||||
* @param value the value
|
||||
* @return the quest item type
|
||||
*/
|
||||
public static QuestItemType smartValueOf(final String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if ("All".equals(value)) {
|
||||
return null;
|
||||
}
|
||||
final String valToCompate = value.trim();
|
||||
for (final QuestItemType v : QuestItemType.values()) {
|
||||
if (v.name().compareToIgnoreCase(valToCompate) == 0) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No element named " + value + " in enum QuestItemType");
|
||||
}
|
||||
|
||||
/**
|
||||
* Value from save key.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the quest item type
|
||||
*/
|
||||
public static QuestItemType valueFromSaveKey(final String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String valToCompate = name.trim();
|
||||
for (final QuestItemType v : QuestItemType.values()) {
|
||||
if (v.getKey().compareToIgnoreCase(valToCompate) == 0) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No element keyed " + name + " in enum QuestItemType");
|
||||
}
|
||||
|
||||
}
|
||||
47
forge-m-base/src/forge/quest/bazaar/QuestItemZeppelin.java
Normal file
47
forge-m-base/src/forge/quest/bazaar/QuestItemZeppelin.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import forge.quest.data.QuestAssets;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestItemZeppelin class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestItemZeppelin.java 14797 2012-03-18 18:09:02Z Max mtg $
|
||||
*/
|
||||
public class QuestItemZeppelin extends QuestItemBasic {
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for QuestItemZeppelin.
|
||||
* </p>
|
||||
*/
|
||||
QuestItemZeppelin() {
|
||||
super(QuestItemType.ZEPPELIN); // , QuestStallManager.GEAR
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final boolean isAvailableForPurchase(QuestAssets qA) {
|
||||
return super.isAvailableForPurchase(qA) && qA.hasItem(QuestItemType.MAP);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
277
forge-m-base/src/forge/quest/bazaar/QuestPetController.java
Normal file
277
forge-m-base/src/forge/quest/bazaar/QuestPetController.java
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
import forge.assets.FImage;
|
||||
import forge.assets.FTextureImage;
|
||||
import forge.item.PaperToken;
|
||||
import forge.quest.data.QuestAssets;
|
||||
import forge.utils.Constants;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Abstract QuestPetAbstract class.
|
||||
* </p>
|
||||
* It's not good to store in a single class pets properties and bazaar sellable
|
||||
* - such is a tradeoff for speed of development
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestPetController.java 24769 2014-02-09 13:56:04Z Hellfish $
|
||||
*/
|
||||
public class QuestPetController implements IQuestBazaarItem {
|
||||
|
||||
/** The level. */
|
||||
@XStreamAsAttribute()
|
||||
private final int maxLevel;
|
||||
|
||||
private final List<QuestPetStats> levels = new ArrayList<QuestPetStats>();
|
||||
|
||||
@XStreamAsAttribute()
|
||||
private final String name;
|
||||
|
||||
@XStreamAlias(value = "desc")
|
||||
private final String description;
|
||||
@XStreamAsAttribute()
|
||||
private final String saveFileKey;
|
||||
@XStreamAsAttribute()
|
||||
private int slot;
|
||||
|
||||
/**
|
||||
*
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param qA quest assets
|
||||
* @return int
|
||||
*/
|
||||
protected int getPetLevel(final QuestAssets qA) {
|
||||
final int level = qA.getPetLevel(this.saveFileKey);
|
||||
return level < 0 ? 0 : level > this.maxLevel ? this.maxLevel : level;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPetCard.
|
||||
* </p>
|
||||
* @param qA quest assets
|
||||
* @return a {@link forge.game.card.Card} object.
|
||||
*/
|
||||
|
||||
public PaperToken getPetCard(final QuestAssets qA) {
|
||||
return this.levels.get(this.getPetLevel(qA)).getCard();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPrice.
|
||||
* </p>
|
||||
* @param qA quest assets
|
||||
* @return a int.
|
||||
*/
|
||||
@Override
|
||||
public final int getBuyingPrice(final QuestAssets qA) {
|
||||
final int level = this.getPetLevel(qA);
|
||||
// we'll buy next level
|
||||
return level >= this.maxLevel ? -1 /* cannot buy */ : this.levels.get(level + 1).getCost();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final int getSellingPrice(final QuestAssets qA) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getUpgradeDescription.
|
||||
* </p>
|
||||
* @param qA quest assets
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public final String getUpgradeDescription(final QuestAssets qA) {
|
||||
return this.levels.get(this.getPetLevel(qA)).getNextLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getIcon.
|
||||
* </p>
|
||||
* @param qA quest assets
|
||||
*/
|
||||
@Override
|
||||
public final FImage getIcon(final QuestAssets qA) {
|
||||
final String path = Constants.CACHE_TOKEN_PICS_DIR;
|
||||
final int level = this.getPetLevel(qA);
|
||||
Texture texture = new Texture(Gdx.files.absolute(path + this.levels.get(level < this.maxLevel ? level + 1 : level).getPicture() + ".jpg"));
|
||||
return new FTextureImage(texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getStats.
|
||||
* </p>
|
||||
* @param qA quest assets
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public final String getStats(final QuestAssets qA) {
|
||||
return this.levels.get(this.getPetLevel(qA)).getStats();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getUpgradedStats.
|
||||
* </p>
|
||||
* @param qA quest assets
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public final String getUpgradedStats(final QuestAssets qA) {
|
||||
final int level = this.getPetLevel(qA);
|
||||
return level >= this.maxLevel ? "N/A" : this.levels.get(level + 1).getStats();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>maxLevel</code>.
|
||||
* </p>
|
||||
*
|
||||
* @return a int.
|
||||
*/
|
||||
public final int getMaxLevel() {
|
||||
return this.maxLevel;
|
||||
}
|
||||
|
||||
// Never to be called, instances will be read from xml
|
||||
private QuestPetController() {
|
||||
this.description = null;
|
||||
this.name = null;
|
||||
this.maxLevel = 0;
|
||||
this.saveFileKey = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPurchaseDescription.
|
||||
* </p>
|
||||
* @param qA quest assets
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
@Override
|
||||
public final String getPurchaseDescription(final QuestAssets qA) {
|
||||
return this.getDescription() + "\n\nCurrent stats: " + this.getStats(qA) + "\nUpgraded stats: "
|
||||
+ this.getUpgradedStats(qA);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>description</code>.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public final String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>name</code>.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
public final String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final int compareTo(final Object o) {
|
||||
return this.name.compareTo(o.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPurchaseName.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
@Override
|
||||
public final String getPurchaseName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public String getStallName() {
|
||||
// return QuestStallManager.PET_SHOP;
|
||||
// }
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* isAvailableForPurchase.
|
||||
* </p>
|
||||
* @param qA quest assets
|
||||
* @return a boolean.
|
||||
*/
|
||||
@Override
|
||||
public boolean isAvailableForPurchase(final QuestAssets qA) {
|
||||
return this.getPetLevel(qA) < this.getMaxLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* onPurchase.
|
||||
* </p>
|
||||
* @param qA quest assets
|
||||
*/
|
||||
@Override
|
||||
public void onPurchase(final QuestAssets qA) {
|
||||
qA.setPetLevel(this.saveFileKey, this.getPetLevel(qA) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* TODO: Write javadoc for this method.
|
||||
* @return String
|
||||
*/
|
||||
public String getSaveFileKey() {
|
||||
return this.saveFileKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getSlot() {
|
||||
return this.slot;
|
||||
}
|
||||
}
|
||||
71
forge-m-base/src/forge/quest/bazaar/QuestPetStats.java
Normal file
71
forge-m-base/src/forge/quest/bazaar/QuestPetStats.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardRules;
|
||||
import forge.item.PaperToken;
|
||||
import forge.util.FileUtil;
|
||||
import forge.utils.Constants;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@XStreamAlias(value = "level")
|
||||
public class QuestPetStats {
|
||||
|
||||
@XStreamAsAttribute()
|
||||
@XStreamAlias(value = "value")
|
||||
private int levelValue;
|
||||
|
||||
@XStreamAsAttribute()
|
||||
@XStreamAlias(value = "pic")
|
||||
private String picture;
|
||||
|
||||
@XStreamAsAttribute()
|
||||
private String stats;
|
||||
|
||||
@XStreamAsAttribute()
|
||||
private String cardFile;
|
||||
|
||||
@XStreamAsAttribute()
|
||||
private int cost;
|
||||
|
||||
@XStreamAsAttribute()
|
||||
private String nextLevel;
|
||||
|
||||
private transient PaperToken petCard = null;
|
||||
|
||||
private QuestPetStats() { }
|
||||
|
||||
public final int getLevelValue() {
|
||||
return levelValue;
|
||||
}
|
||||
|
||||
public final String getPicture() {
|
||||
return picture;
|
||||
}
|
||||
|
||||
public final String getStats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
public final PaperToken getCard() {
|
||||
if (null == petCard) {
|
||||
List<String> cardLines = FileUtil.readFile(new File(Constants.CARD_DATA_PETS_DIR, cardFile));
|
||||
CardRules rules = CardRules.fromScript(cardLines);
|
||||
petCard = new PaperToken(rules, CardEdition.UNKNOWN, picture);
|
||||
}
|
||||
return petCard;
|
||||
}
|
||||
|
||||
public final int getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
public final String getNextLevel() {
|
||||
return nextLevel;
|
||||
}
|
||||
}
|
||||
134
forge-m-base/src/forge/quest/bazaar/QuestPetStorage.java
Normal file
134
forge-m-base/src/forge/quest/bazaar/QuestPetStorage.java
Normal file
@@ -0,0 +1,134 @@
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
|
||||
import forge.quest.data.QuestAssets;
|
||||
import forge.utils.IgnoringXStream;
|
||||
import forge.utils.XmlUtil;
|
||||
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class QuestPetStorage {
|
||||
|
||||
private Map<Integer, List<QuestPetController>> petsBySlot = new HashMap<Integer, List<QuestPetController>>();
|
||||
|
||||
private Map<String, QuestPetController> petsByName = new HashMap<String, QuestPetController>();
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
*
|
||||
* @param file File
|
||||
*/
|
||||
public QuestPetStorage(final File file) {
|
||||
DocumentBuilder builder;
|
||||
try {
|
||||
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final Document document = builder.parse(file);
|
||||
|
||||
final XStream xs = new IgnoringXStream();
|
||||
xs.autodetectAnnotations(true);
|
||||
|
||||
final NodeList xmlPets = document.getElementsByTagName("pets").item(0).getChildNodes();
|
||||
for (int iN = 0; iN < xmlPets.getLength(); iN++) {
|
||||
final Node n = xmlPets.item(iN);
|
||||
if (n.getNodeType() != Node.ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final Attr att = document.createAttribute("resolves-to");
|
||||
att.setValue(QuestPetController.class.getCanonicalName());
|
||||
n.getAttributes().setNamedItem(att);
|
||||
final String sXml = XmlUtil.nodeToString(n);
|
||||
final QuestPetController petCtrl = (QuestPetController) xs.fromXML(sXml);
|
||||
this.addToMap(petCtrl);
|
||||
}
|
||||
|
||||
} catch (final SAXException e) {
|
||||
e.printStackTrace();
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (final ParserConfigurationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*
|
||||
* @param petCtrl
|
||||
*/
|
||||
private void addToMap(final QuestPetController petCtrl) {
|
||||
final int iSlot = petCtrl.getSlot();
|
||||
List<QuestPetController> list = this.petsBySlot.get(Integer.valueOf(iSlot));
|
||||
if (null == list) {
|
||||
list = new ArrayList<QuestPetController>();
|
||||
this.petsBySlot.put(Integer.valueOf(iSlot), list);
|
||||
}
|
||||
this.petsByName.put(petCtrl.getName(), petCtrl);
|
||||
list.add(petCtrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*
|
||||
* @param petName String
|
||||
* @return QuestPetController
|
||||
*/
|
||||
public QuestPetController getPet(final String petName) {
|
||||
return this.petsByName.get(petName);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*
|
||||
* @param iSlot int
|
||||
* @param qA QuestAssets
|
||||
* @return List
|
||||
*/
|
||||
public List<QuestPetController> getAvaliablePets(final int iSlot, final QuestAssets qA) {
|
||||
final List<QuestPetController> result = new ArrayList<QuestPetController>();
|
||||
final List<QuestPetController> allPossible = this.petsBySlot.get(Integer.valueOf(iSlot));
|
||||
if (null != allPossible) {
|
||||
for (final QuestPetController c : allPossible) {
|
||||
if (qA.getPetLevel(c.getSaveFileKey()) > 0) {
|
||||
result.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param iSlot int
|
||||
* @return List<QuestPetController>
|
||||
*/
|
||||
public List<QuestPetController> getAllPets(final int iSlot) {
|
||||
final List<QuestPetController> result = new ArrayList<QuestPetController>();
|
||||
final List<QuestPetController> allPossible = this.petsBySlot.get(Integer.valueOf(iSlot));
|
||||
if (null != allPossible) {
|
||||
for (final QuestPetController c : allPossible) {
|
||||
result.add(c);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
115
forge-m-base/src/forge/quest/bazaar/QuestStallDefinition.java
Normal file
115
forge-m-base/src/forge/quest/bazaar/QuestStallDefinition.java
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.bazaar;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
|
||||
|
||||
import forge.assets.FImage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestStallDefinition class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestStallDefinition.java 24769 2014-02-09 13:56:04Z Hellfish $
|
||||
*/
|
||||
@XStreamAlias("stall")
|
||||
public class QuestStallDefinition {
|
||||
|
||||
/** The name. */
|
||||
@XStreamAsAttribute
|
||||
private final String name;
|
||||
|
||||
/** The display name. */
|
||||
@XStreamAsAttribute
|
||||
private final String displayName;
|
||||
|
||||
@XStreamAsAttribute
|
||||
private final FImage icon;
|
||||
|
||||
private final String description;
|
||||
|
||||
private final List<String> items;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for QuestStallDefinition.
|
||||
* </p> Not used anyway
|
||||
*
|
||||
* @param name
|
||||
* a {@link java.lang.String} object.
|
||||
* @param displayName
|
||||
* a {@link java.lang.String} object.
|
||||
* @param description
|
||||
* a {@link java.lang.String} object.
|
||||
* @param icon0
|
||||
* a {@link javax.swing.ImageIcon} object.
|
||||
*/
|
||||
private QuestStallDefinition() {
|
||||
name = null;
|
||||
displayName = null;
|
||||
description = null;
|
||||
items = new ArrayList<String>();
|
||||
icon = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fluff.
|
||||
*
|
||||
* @return the fluff
|
||||
*/
|
||||
public String getFluff() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the icon.
|
||||
*
|
||||
* @return the icon
|
||||
*/
|
||||
public FImage getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display name.
|
||||
*
|
||||
* @return the displayName
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public List<String> getItems() {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
3
forge-m-base/src/forge/quest/bazaar/package-info.java
Normal file
3
forge-m-base/src/forge/quest/bazaar/package-info.java
Normal file
@@ -0,0 +1,3 @@
|
||||
/** Forge Card Game. */
|
||||
package forge.quest.bazaar;
|
||||
|
||||
153
forge-m-base/src/forge/quest/data/GameFormatQuest.java
Normal file
153
forge-m-base/src/forge/quest/data/GameFormatQuest.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.data;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.card.CardEdition;
|
||||
import forge.game.GameFormat;
|
||||
import forge.model.FModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* This is an alternate game format type, the main difference is that this
|
||||
* is not immutable. This class is necessary because we may wish to update
|
||||
* its contents in certain circumstances, and it was safer to create a new
|
||||
* class than to make the preset game formats modifiable.
|
||||
*/
|
||||
public final class GameFormatQuest extends GameFormat {
|
||||
|
||||
private final boolean allowUnlocks;
|
||||
private int unlocksUsed = 0;
|
||||
|
||||
/**
|
||||
* Instantiates a new game format based on two lists.
|
||||
*
|
||||
* @param newName
|
||||
* String, the name
|
||||
* @param setsToAllow
|
||||
* List<String>, these are the allowed sets
|
||||
* @param cardsToBan
|
||||
* List<String>, these will be the banned cards
|
||||
*/
|
||||
public GameFormatQuest(final String newName, final List<String> setsToAllow, final List<String> cardsToBan) {
|
||||
super(newName, setsToAllow, cardsToBan);
|
||||
allowUnlocks = false;
|
||||
}
|
||||
|
||||
public GameFormatQuest(final String newName, final List<String> setsToAllow, final List<String> cardsToBan, boolean allowSetUnlocks) {
|
||||
super(newName, setsToAllow, cardsToBan);
|
||||
allowUnlocks = allowSetUnlocks;
|
||||
}
|
||||
/**
|
||||
* Instantiates a new game format based on an existing format.
|
||||
*
|
||||
* @param toCopy
|
||||
* an existing format
|
||||
* @param allowSetUnlocks
|
||||
*/
|
||||
public GameFormatQuest(final GameFormat toCopy, boolean allowSetUnlocks) {
|
||||
super(toCopy.getName(), toCopy.getAllowedSetCodes(), toCopy.getBannedCardNames(), toCopy.getRestrictedCards(), toCopy.getIndex());
|
||||
allowUnlocks = allowSetUnlocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the list of excluded sets.
|
||||
*
|
||||
* @return unmodifiable list of excluded sets.
|
||||
*/
|
||||
public List<String> getLockedSets() {
|
||||
|
||||
List<String> exSets = new ArrayList<String>();
|
||||
if (this.allowedSetCodes.isEmpty()) {
|
||||
return exSets;
|
||||
}
|
||||
|
||||
for (CardEdition ce : FModel.getMagicDb().getEditions()) {
|
||||
if (!isSetLegal(ce.getCode())) {
|
||||
exSets.add(ce.getCode());
|
||||
}
|
||||
}
|
||||
return exSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a set to allowed set codes.
|
||||
*
|
||||
* @param setCode String, set code.
|
||||
*/
|
||||
public void unlockSet(final String setCode) {
|
||||
if (!canUnlockSets() || this.allowedSetCodes_ro.isEmpty() || this.allowedSetCodes_ro.contains(setCode)) {
|
||||
return;
|
||||
}
|
||||
this.allowedSetCodes.add(setCode);
|
||||
unlocksUsed++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current format contains sets with snow-land (horrible hack...).
|
||||
* @return boolean, contains snow-land sets.
|
||||
*
|
||||
*/
|
||||
public boolean hasSnowLands() {
|
||||
return (this.isSetLegal("ICE") || this.isSetLegal("CSP"));
|
||||
}
|
||||
|
||||
public boolean canUnlockSets() {
|
||||
return allowUnlocks;
|
||||
}
|
||||
|
||||
public int getUnlocksUsed() {
|
||||
return unlocksUsed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The Class Predicates.
|
||||
*/
|
||||
public abstract static class Predicates {
|
||||
/**
|
||||
* Checks if is legal in quest format.
|
||||
*
|
||||
* @param qFormat the format
|
||||
* @return the predicate
|
||||
*/
|
||||
public static Predicate<CardEdition> isLegalInFormatQuest(final GameFormatQuest qFormat) {
|
||||
return new LegalInFormatQuest(qFormat);
|
||||
}
|
||||
|
||||
private static class LegalInFormatQuest implements Predicate<CardEdition> {
|
||||
private final GameFormatQuest qFormat;
|
||||
|
||||
public LegalInFormatQuest(final GameFormatQuest fmt) {
|
||||
this.qFormat = fmt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(final CardEdition subject) {
|
||||
return this.qFormat.isSetLegal(subject.getCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
176
forge-m-base/src/forge/quest/data/QuestAchievements.java
Normal file
176
forge-m-base/src/forge/quest/data/QuestAchievements.java
Normal file
@@ -0,0 +1,176 @@
|
||||
package forge.quest.data;
|
||||
|
||||
import forge.model.FModel;
|
||||
import forge.quest.data.QuestPreferences.DifficultyPrefs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class QuestAchievements {
|
||||
|
||||
// Challenge history
|
||||
/** The challenges played. */
|
||||
private int challengesPlayed = 0;
|
||||
|
||||
private List<String> completedChallenges = new ArrayList<String>();
|
||||
private List<String> currentChallenges = new ArrayList<String>();
|
||||
|
||||
private int win;
|
||||
private int winstreakBest = 0;
|
||||
private int winstreakCurrent = 0;
|
||||
private int lost;
|
||||
|
||||
// Difficulty - will store only index from now.
|
||||
private int difficulty;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param diff   int
|
||||
*/
|
||||
public QuestAchievements(int diff) {
|
||||
difficulty = diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param mode
|
||||
*/
|
||||
/**
|
||||
* Adds the win.
|
||||
*/
|
||||
public void addWin() { // changes getRank()
|
||||
this.win++;
|
||||
this.winstreakCurrent++;
|
||||
|
||||
if (this.winstreakCurrent > this.winstreakBest) {
|
||||
this.winstreakBest = this.winstreakCurrent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Challenge performance
|
||||
/**
|
||||
* Gets the challenges played.
|
||||
*
|
||||
* @return the challenges played
|
||||
*/
|
||||
public int getChallengesPlayed() {
|
||||
return this.challengesPlayed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the challenges played.
|
||||
*/
|
||||
public void addChallengesPlayed() {
|
||||
this.challengesPlayed++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns stored list of non-repeatable challenge IDs.
|
||||
*
|
||||
* @return List<Integer>
|
||||
*/
|
||||
public List<String> getLockedChallenges() {
|
||||
return this.completedChallenges;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* addCompletedChallenge.
|
||||
* </p>
|
||||
* Add non-repeatable challenge ID to list.
|
||||
*
|
||||
* @param i
|
||||
* the i
|
||||
*/
|
||||
public void addLockedChallenge(final String i) {
|
||||
this.completedChallenges.add(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a list of current challenges.
|
||||
*
|
||||
* @return List<Integer>
|
||||
*/
|
||||
public List<String> getCurrentChallenges() {
|
||||
if (this.currentChallenges == null) {
|
||||
this.currentChallenges = new ArrayList<String>();
|
||||
}
|
||||
|
||||
return this.currentChallenges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stored list of current challenges.
|
||||
*
|
||||
* @param lst0 List<Integer>
|
||||
*/
|
||||
public void setCurrentChallenges(final List<String> lst0) {
|
||||
this.currentChallenges = lst0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the lost.
|
||||
*/
|
||||
public void addLost() {
|
||||
this.lost++;
|
||||
this.winstreakCurrent = 0;
|
||||
}
|
||||
// Level, read-only ( note: it increments in addWin() )
|
||||
/**
|
||||
* Gets the level.
|
||||
*
|
||||
* @return the level
|
||||
*/
|
||||
public int getLevel() {
|
||||
final int winsToLvlUp = FModel.getQuestPreferences().getPrefInt(DifficultyPrefs.WINS_RANKUP, difficulty);
|
||||
return this.win / winsToLvlUp;
|
||||
}
|
||||
// Wins & Losses
|
||||
/**
|
||||
* Gets the lost.
|
||||
*
|
||||
* @return the lost
|
||||
*/
|
||||
public int getLost() {
|
||||
return this.lost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the win.
|
||||
*
|
||||
* @return the win
|
||||
*/
|
||||
public int getWin() {
|
||||
return win;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the win streak best.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getWinStreakBest() {
|
||||
return winstreakBest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the win streak current.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getWinStreakCurrent() {
|
||||
return winstreakCurrent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the difficulty index.
|
||||
*
|
||||
* @return the difficulty index
|
||||
*/
|
||||
public int getDifficulty() {
|
||||
return this.difficulty;
|
||||
}
|
||||
|
||||
}
|
||||
266
forge-m-base/src/forge/quest/data/QuestAssets.java
Normal file
266
forge-m-base/src/forge/quest/data/QuestAssets.java
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Nate
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.data;
|
||||
|
||||
import forge.deck.Deck;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.QuestDeckMap;
|
||||
import forge.quest.QuestMode;
|
||||
import forge.quest.QuestUtilCards;
|
||||
import forge.quest.bazaar.QuestItemType;
|
||||
import forge.quest.data.QuestPreferences.QPref;
|
||||
import forge.util.ItemPool;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** */
|
||||
public class QuestAssets {
|
||||
|
||||
// Cards associated with quest
|
||||
/** The card pool. */
|
||||
private final ItemPool<PaperCard> cardPool = new ItemPool<PaperCard>(PaperCard.class); // player's
|
||||
/** The credits. */
|
||||
private long credits; // this money is good for all modes
|
||||
// game
|
||||
// with
|
||||
|
||||
// Decks collected by player
|
||||
/** The my decks. */
|
||||
private final HashMap<String, Deck> myDecks = new HashMap<String, Deck>();
|
||||
// current
|
||||
// shop
|
||||
// list
|
||||
/** The new card list. */
|
||||
private final ItemPool<InventoryItem> newCardList = new ItemPool<InventoryItem>(InventoryItem.class); // cards
|
||||
// belonging
|
||||
/** The shop list. */
|
||||
private final ItemPool<InventoryItem> shopList = new ItemPool<InventoryItem>(InventoryItem.class); // the
|
||||
// gadgets
|
||||
|
||||
/** The inventory items. */
|
||||
private final Map<QuestItemType, QuestItemCondition> inventoryItems = new EnumMap<QuestItemType, QuestItemCondition>(
|
||||
QuestItemType.class);
|
||||
|
||||
// Much the same like other map, but keyed by string (to support a lot of custom pets)
|
||||
private final Map<String, QuestItemCondition> combatPets = new HashMap<String, QuestItemCondition>();
|
||||
/**
|
||||
* Checks for item.
|
||||
*
|
||||
* @param itemType the item type
|
||||
* @return true, if successful
|
||||
*/
|
||||
public final boolean hasItem(final QuestItemType itemType) {
|
||||
return this.inventoryItems.containsKey(itemType) && (this.inventoryItems.get(itemType).getLevel() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item level.
|
||||
*
|
||||
* @param itemType the item type
|
||||
* @return the item level
|
||||
*/
|
||||
public final int getItemLevel(final QuestItemType itemType) {
|
||||
final QuestItemCondition state = this.inventoryItems.get(itemType);
|
||||
return state == null ? 0 : state.getLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item condition.
|
||||
*
|
||||
* @param itemType the item type
|
||||
* @param <T> extends QuestItemCondition
|
||||
* @return T the item condition
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T extends QuestItemCondition> T getItemCondition(final QuestItemType itemType) {
|
||||
QuestItemCondition current = this.inventoryItems.get(itemType);
|
||||
if (!current.getClass().equals(itemType.getModelClass())) {
|
||||
try {
|
||||
QuestItemCondition modern = itemType.getModelClass().newInstance();
|
||||
modern.takeDataFrom(current);
|
||||
current = modern;
|
||||
inventoryItems.put(itemType, modern);
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
return (T) current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item level.
|
||||
*
|
||||
* @param itemType the item type
|
||||
* @param level the level
|
||||
*/
|
||||
public final void setItemLevel(final QuestItemType itemType, final int level) {
|
||||
QuestItemCondition cond = this.inventoryItems.get(itemType);
|
||||
if (null == cond) {
|
||||
try { // care to set appropriate state class here
|
||||
cond = itemType.getModelClass().newInstance();
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
cond = new QuestItemCondition();
|
||||
}
|
||||
this.inventoryItems.put(itemType, cond);
|
||||
}
|
||||
cond.setLevel(level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name String
|
||||
* @return int
|
||||
*/
|
||||
public final int getPetLevel(final String name) {
|
||||
final QuestItemCondition state = this.combatPets.get(name);
|
||||
return state == null ? 0 : state.getLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name   String
|
||||
* @param <T> extends QuestItemCondition
|
||||
* @return <T>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T extends QuestItemCondition> T getPetCondition(final String name) {
|
||||
return (T) this.combatPets.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name String
|
||||
* @param level int
|
||||
*/
|
||||
public final void setPetLevel(final String name, final int level) {
|
||||
QuestItemCondition cond = this.combatPets.get(name);
|
||||
if (null == cond) {
|
||||
cond = new QuestItemCondition(); // pets have only level that should be serialized for now
|
||||
this.combatPets.put(name, cond);
|
||||
}
|
||||
cond.setLevel(level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new quest assets.
|
||||
*/
|
||||
public QuestAssets(GameFormatQuest useFormat) {
|
||||
final QuestPreferences prefs = FModel.getQuestPreferences();
|
||||
int snowLands = prefs.getPrefInt(QPref.STARTING_SNOW_LANDS);
|
||||
if (useFormat != null && !useFormat.hasSnowLands()) {
|
||||
snowLands = 0;
|
||||
}
|
||||
final ItemPool<PaperCard> lands = QuestUtilCards.generateBasicLands(
|
||||
prefs.getPrefInt(QPref.STARTING_BASIC_LANDS), snowLands, useFormat);
|
||||
this.getCardPool().addAll(lands);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the credits.
|
||||
*
|
||||
* @return the credits
|
||||
*/
|
||||
public long getCredits() {
|
||||
return this.credits;
|
||||
}
|
||||
|
||||
// Life (only fantasy)
|
||||
/**
|
||||
* Gets the life.
|
||||
*
|
||||
* @param mode the mode
|
||||
* @return the life
|
||||
*/
|
||||
public int getLife(final QuestMode mode) {
|
||||
final int base = mode.equals(QuestMode.Fantasy) ? 15 : 20;
|
||||
return (base + this.getItemLevel(QuestItemType.ELIXIR_OF_LIFE)) - this.getItemLevel(QuestItemType.POUND_FLESH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the new card list.
|
||||
*
|
||||
* @return the newCardList
|
||||
*/
|
||||
public ItemPool<InventoryItem> getNewCardList() {
|
||||
return this.newCardList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the shop list.
|
||||
*
|
||||
* @return the shopList
|
||||
*/
|
||||
public ItemPool<InventoryItem> getShopList() {
|
||||
return this.shopList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the credits.
|
||||
*
|
||||
* @param credits0
|
||||
* the credits to set
|
||||
*/
|
||||
public void setCredits(final long credits0) {
|
||||
this.credits = credits0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Credits
|
||||
/**
|
||||
* Adds the credits.
|
||||
*
|
||||
* @param c
|
||||
* the c
|
||||
*/
|
||||
public void addCredits(final long c) {
|
||||
this.setCredits(this.getCredits() + c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the card pool.
|
||||
*
|
||||
* @return the cardPool
|
||||
*/
|
||||
public ItemPool<PaperCard> getCardPool() {
|
||||
return this.cardPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtract credits.
|
||||
*
|
||||
* @param c
|
||||
* the c
|
||||
*/
|
||||
public void subtractCredits(final long c) {
|
||||
this.setCredits(this.getCredits() > c ? this.getCredits() - c : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the deck storage
|
||||
*/
|
||||
public QuestDeckMap getDeckStorage() {
|
||||
return new QuestDeckMap(this.myDecks);
|
||||
}
|
||||
|
||||
}
|
||||
217
forge-m-base/src/forge/quest/data/QuestData.java
Normal file
217
forge-m-base/src/forge/quest/data/QuestData.java
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.data;
|
||||
|
||||
import forge.game.GameFormat;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.QuestMode;
|
||||
import forge.quest.io.QuestDataIO;
|
||||
import forge.utils.Constants;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
//when you create QuestDataOld and AFTER you copy the AI decks over
|
||||
//you have to call one of these two methods below
|
||||
//see Gui_QuestOptions for more details
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestData class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestData.java 24769 2014-02-09 13:56:04Z Hellfish $
|
||||
*/
|
||||
public final class QuestData {
|
||||
/** Holds the latest version of the Quest Data. */
|
||||
public static final int CURRENT_VERSION_NUMBER = 8;
|
||||
|
||||
// This field places the version number into QD instance,
|
||||
// but only when the object is created through the constructor
|
||||
// DO NOT RENAME THIS FIELD
|
||||
/** The version number. */
|
||||
private int versionNumber = QuestData.CURRENT_VERSION_NUMBER;
|
||||
|
||||
private GameFormatQuest format;
|
||||
private String name;
|
||||
|
||||
// Quest mode - there should be an enum :(
|
||||
/** The mode. */
|
||||
private QuestMode mode;
|
||||
|
||||
// Quest world ID, if any
|
||||
private String worldId;
|
||||
// gadgets
|
||||
|
||||
private final QuestAssets assets;
|
||||
private final QuestAchievements achievements;
|
||||
private final Map<Integer, String> petSlots = new HashMap<Integer, String>();
|
||||
private boolean isCharmActive = false;
|
||||
|
||||
/**
|
||||
* Instantiates a new quest data.
|
||||
* @param mode2
|
||||
* quest mode
|
||||
* @param diff
|
||||
* achievement diff
|
||||
* @param name2
|
||||
* quest name
|
||||
* @param userFormat
|
||||
* user-defined format, if any (null if none).
|
||||
* @param allowSetUnlocks
|
||||
* allow set unlocking during quest
|
||||
* @param startingWorld
|
||||
* starting world
|
||||
*/
|
||||
public QuestData(String name0, int diff, QuestMode mode0, GameFormat userFormat,
|
||||
boolean allowSetUnlocks, final String startingWorld) {
|
||||
this.name = name0;
|
||||
|
||||
if (userFormat != null) {
|
||||
this.format = new GameFormatQuest(userFormat, allowSetUnlocks);
|
||||
}
|
||||
this.mode = mode0;
|
||||
this.achievements = new QuestAchievements(diff);
|
||||
this.assets = new QuestAssets(format);
|
||||
this.worldId = startingWorld;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mode.
|
||||
*
|
||||
* @return the mode
|
||||
*/
|
||||
public QuestMode getMode() {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the persistent format, null if not assigned.
|
||||
*
|
||||
* @return GameFormatQuest, the persistent format
|
||||
*/
|
||||
public GameFormatQuest getFormat() {
|
||||
return this.format;
|
||||
}
|
||||
|
||||
// SERIALIZATION - related things
|
||||
// This must be called by XML-serializer via reflection
|
||||
/**
|
||||
* Read resolve.
|
||||
*
|
||||
* @return the object
|
||||
*/
|
||||
public Object readResolve() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save data.
|
||||
*/
|
||||
public void saveData() {
|
||||
QuestDataIO.saveData(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version number.
|
||||
*
|
||||
* @return the versionNumber
|
||||
*/
|
||||
public int getVersionNumber() {
|
||||
return this.versionNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the version number.
|
||||
*
|
||||
* @param versionNumber0
|
||||
* the versionNumber to set
|
||||
*/
|
||||
public void setVersionNumber(final int versionNumber0) {
|
||||
this.versionNumber = versionNumber0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name.
|
||||
*
|
||||
* @return {@link java.lang.String}
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this quest the name.
|
||||
*
|
||||
* @param newName
|
||||
* the new name to set
|
||||
*/
|
||||
public void rename(final String newName) {
|
||||
File newpath = new File(Constants.QUEST_SAVE_DIR, newName + ".dat");
|
||||
File oldpath = new File(Constants.QUEST_SAVE_DIR, this.name + ".dat");
|
||||
oldpath.renameTo(newpath);
|
||||
|
||||
this.name = newName;
|
||||
QuestDataIO.saveData(this);
|
||||
}
|
||||
|
||||
public QuestAssets getAssets() {
|
||||
return assets;
|
||||
}
|
||||
|
||||
public Map<Integer, String> getPetSlots() {
|
||||
return petSlots;
|
||||
}
|
||||
|
||||
public QuestAchievements getAchievements() {
|
||||
return achievements;
|
||||
}
|
||||
|
||||
public String getWorldId() {
|
||||
return worldId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the world id to null or a legal world id.
|
||||
* @param newId
|
||||
* String, the world id to set (must be null or legal).
|
||||
*/
|
||||
public void setWorldId(final String newId) {
|
||||
if (newId != null && FModel.getWorlds().get(newId) == null) {
|
||||
throw new RuntimeException("Tried to set illegal (unknown) world id: " + newId);
|
||||
}
|
||||
|
||||
worldId = newId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the isCharmActive
|
||||
*/
|
||||
public boolean isCharmActive() {
|
||||
return isCharmActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isCharmActive the isCharmActive to set
|
||||
*/
|
||||
public void setCharmActive(boolean isCharmActive) {
|
||||
this.isCharmActive = isCharmActive;
|
||||
}
|
||||
}
|
||||
27
forge-m-base/src/forge/quest/data/QuestItemCondition.java
Normal file
27
forge-m-base/src/forge/quest/data/QuestItemCondition.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package forge.quest.data;
|
||||
|
||||
/**
|
||||
* This class should store the quest items' properties that are to be serialized.
|
||||
*
|
||||
*/
|
||||
public class QuestItemCondition {
|
||||
private int level;
|
||||
|
||||
/** @return int */
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/** @param level int */
|
||||
public void setLevel(int level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy data from the parameter instance to 'this' instance.
|
||||
* @param source QuestItemCondition
|
||||
*/
|
||||
public void takeDataFrom(QuestItemCondition source) {
|
||||
this.level = source.level;
|
||||
}
|
||||
}
|
||||
261
forge-m-base/src/forge/quest/data/QuestPreferences.java
Normal file
261
forge-m-base/src/forge/quest/data/QuestPreferences.java
Normal file
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import forge.utils.Constants;
|
||||
import forge.utils.PreferencesStore;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class QuestPreferences extends PreferencesStore<QuestPreferences.QPref> implements Serializable {
|
||||
/**
|
||||
* Preference identifiers, and their default values.
|
||||
*/
|
||||
public static enum QPref {
|
||||
|
||||
// How many of each rarity comes in a won booster pack
|
||||
BOOSTER_COMMONS("11"),
|
||||
BOOSTER_UNCOMMONS("3"),
|
||||
BOOSTER_RARES("1"),
|
||||
// The preferred format of the won booster pack
|
||||
BOOSTER_FORMAT("Standard"),
|
||||
|
||||
// How many credits are lost for losing a match
|
||||
PENALTY_LOSS("15"),
|
||||
|
||||
// Currently chosen quest and deck
|
||||
CURRENT_QUEST("DEFAULT"),
|
||||
CURRENT_DECK("DEFAULT"),
|
||||
|
||||
// All of the rewards given out End of Match
|
||||
// Awarded to every match winner
|
||||
REWARDS_BASE("25"),
|
||||
// Didn't lose a game in the match
|
||||
REWARDS_UNDEFEATED("25"),
|
||||
// For each of your previous wins gain a small multiplier
|
||||
// This is here to award long quests with more money for buying expensive cards
|
||||
REWARDS_WINS_MULTIPLIER("0.3"),
|
||||
|
||||
// Winning each game by other means "Poison", "Milling" or "Alternative" Win
|
||||
REWARDS_POISON("50"),
|
||||
REWARDS_MILLED("40"),
|
||||
REWARDS_ALTERNATIVE("100"),
|
||||
|
||||
// If you Mulligan to 0 to start a game
|
||||
REWARDS_MULLIGAN0("500"),
|
||||
|
||||
// How many turns it took you to win the game
|
||||
REWARDS_TURN15("5"),
|
||||
REWARDS_TURN10("50"),
|
||||
REWARDS_TURN5("250"),
|
||||
REWARDS_TURN1("1500"),
|
||||
|
||||
// How many basic your starting pool has (if appropriate)
|
||||
STARTING_BASIC_LANDS("20"),
|
||||
STARTING_SNOW_LANDS("5"),
|
||||
|
||||
// Starting pool color bias effect
|
||||
STARTING_POOL_COLOR_BIAS("6"),
|
||||
|
||||
// Commons in your starting pool, by difficulty
|
||||
STARTING_COMMONS_EASY("82"),
|
||||
STARTING_COMMONS_MEDIUM("80"),
|
||||
STARTING_COMMONS_HARD("78"),
|
||||
STARTING_COMMONS_EXPERT("76"),
|
||||
|
||||
// Uncommons in your starting pool, by difficulty
|
||||
STARTING_UNCOMMONS_EASY("40"),
|
||||
STARTING_UNCOMMONS_MEDIUM("36"),
|
||||
STARTING_UNCOMMONS_HARD("32"),
|
||||
STARTING_UNCOMMONS_EXPERT("28"),
|
||||
|
||||
// Rares in your starting pool, by difficulty
|
||||
STARTING_RARES_EASY("20"),
|
||||
STARTING_RARES_MEDIUM("18"),
|
||||
STARTING_RARES_HARD("16"),
|
||||
STARTING_RARES_EXPERT("15"),
|
||||
|
||||
// Credits you start the quest with, by difficulty
|
||||
STARTING_CREDITS_EASY("250"),
|
||||
STARTING_CREDITS_MEDIUM("200"),
|
||||
STARTING_CREDITS_HARD("150"),
|
||||
STARTING_CREDITS_EXPERT("100"),
|
||||
|
||||
// Matches won per booster award, by difficulty
|
||||
WINS_BOOSTER_EASY("1"),
|
||||
WINS_BOOSTER_MEDIUM("1"),
|
||||
WINS_BOOSTER_HARD("2"),
|
||||
WINS_BOOSTER_EXPERT("2"),
|
||||
|
||||
// Matches won per increased rank, by difficulty
|
||||
// Rank affects how many packs are opened for singles in the spell shop
|
||||
WINS_RANKUP_EASY("3"),
|
||||
WINS_RANKUP_MEDIUM("4"),
|
||||
WINS_RANKUP_HARD("5"),
|
||||
WINS_RANKUP_EXPERT("6"),
|
||||
|
||||
// Matches won to unlock Medium Opponents, by difficulty
|
||||
WINS_MEDIUMAI_EASY("10"),
|
||||
WINS_MEDIUMAI_MEDIUM("9"),
|
||||
WINS_MEDIUMAI_HARD("8"),
|
||||
WINS_MEDIUMAI_EXPERT("7"),
|
||||
|
||||
// Matches won to unlock Hard Opponents, by difficulty
|
||||
WINS_HARDAI_EASY("20"),
|
||||
WINS_HARDAI_MEDIUM("18"),
|
||||
WINS_HARDAI_HARD("16"),
|
||||
WINS_HARDAI_EXPERT("14"),
|
||||
|
||||
// Matches won to unlock Expert Opponents, by difficulty
|
||||
WINS_EXPERTAI_EASY("40"),
|
||||
WINS_EXPERTAI_MEDIUM("36"),
|
||||
WINS_EXPERTAI_HARD("32"),
|
||||
WINS_EXPERTAI_EXPERT("28"),
|
||||
|
||||
// Maximum amount of "Packs" opened by the Shop and available as singles
|
||||
SHOP_MAX_PACKS("6"),
|
||||
|
||||
// Rarity distribution of Singles in an Opened Shop Pack
|
||||
SHOP_SINGLES_COMMON("7"),
|
||||
SHOP_SINGLES_UNCOMMON("3"),
|
||||
SHOP_SINGLES_RARE("1"),
|
||||
|
||||
// How many wins it takes to open an additional pack in the shop
|
||||
SHOP_WINS_FOR_ADDITIONAL_PACK("10"),
|
||||
// How many packs the shop start with.
|
||||
SHOP_STARTING_PACKS("4");
|
||||
|
||||
private final String strDefaultVal;
|
||||
|
||||
/**
|
||||
* Instantiates a new q pref.
|
||||
*
|
||||
* @param s0
|
||||
*   {@link java.lang.String}
|
||||
*/
|
||||
QPref(final String s0) {
|
||||
this.strDefaultVal = s0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default.
|
||||
*
|
||||
* @return {@link java.lang.String}
|
||||
*/
|
||||
public String getDefault() {
|
||||
return this.strDefaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
public static enum DifficultyPrefs {
|
||||
STARTING_COMMONS,
|
||||
STARTING_UNCOMMONS,
|
||||
STARTING_RARES,
|
||||
STARTING_CREDITS,
|
||||
WINS_BOOSTER,
|
||||
WINS_RANKUP,
|
||||
WINS_MEDIUMAI,
|
||||
WINS_HARDAI,
|
||||
WINS_EXPERTAI
|
||||
}
|
||||
|
||||
/** Instantiates a QuestPreferences object. */
|
||||
public QuestPreferences() {
|
||||
super(Constants.QUEST_PREFS_FILE, QPref.class);
|
||||
}
|
||||
|
||||
protected QPref[] getEnumValues() {
|
||||
return QPref.values();
|
||||
}
|
||||
|
||||
protected QPref valueOf(String name) {
|
||||
try {
|
||||
return QPref.valueOf(name);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected String getPrefDefault(QPref key) {
|
||||
return key.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a preference value according to a difficulty index.
|
||||
*/
|
||||
public String getPref(DifficultyPrefs pref, int difficultyIndex) {
|
||||
String newQPref = pref.toString();
|
||||
|
||||
switch (difficultyIndex) {
|
||||
case 0:
|
||||
newQPref += "_EASY";
|
||||
break;
|
||||
case 1:
|
||||
newQPref += "_MEDIUM";
|
||||
break;
|
||||
case 2:
|
||||
newQPref += "_HARD";
|
||||
break;
|
||||
case 3:
|
||||
newQPref += "_EXPERT";
|
||||
break;
|
||||
default:
|
||||
try {
|
||||
throw new Exception();
|
||||
} catch (final Exception e1) {
|
||||
System.err.println("Difficulty index out of bounds: " + difficultyIndex);
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return getPref(QPref.valueOf(newQPref));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a difficulty-indexed preference value, as an int.
|
||||
*/
|
||||
public int getPrefInt(DifficultyPrefs pref, int difficultyIndex) {
|
||||
return Integer.parseInt(this.getPref(pref, difficultyIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the difficulty.
|
||||
*/
|
||||
public static String getDifficulty(int difficultyIndex) {
|
||||
String s;
|
||||
switch (difficultyIndex) {
|
||||
case 1:
|
||||
s = "EASY";
|
||||
break;
|
||||
case 2:
|
||||
s = "MEDIUM";
|
||||
break;
|
||||
case 3:
|
||||
s = "HARD";
|
||||
break;
|
||||
case 4:
|
||||
s = "EXPERT";
|
||||
break;
|
||||
default:
|
||||
s = "UNKNOWN";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
3
forge-m-base/src/forge/quest/data/package-info.java
Normal file
3
forge-m-base/src/forge/quest/data/package-info.java
Normal file
@@ -0,0 +1,3 @@
|
||||
/** Forge Card Game. */
|
||||
package forge.quest.data;
|
||||
|
||||
73
forge-m-base/src/forge/quest/io/QuestChallengeReader.java
Normal file
73
forge-m-base/src/forge/quest/io/QuestChallengeReader.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package forge.quest.io;
|
||||
|
||||
import forge.ImageKeys;
|
||||
import forge.deck.io.DeckSerializer;
|
||||
import forge.deck.io.DeckStorage;
|
||||
import forge.quest.QuestEventChallenge;
|
||||
import forge.quest.QuestEventDifficulty;
|
||||
import forge.util.FileSection;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.storage.StorageReaderFolder;
|
||||
import forge.utils.Constants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class QuestChallengeReader extends StorageReaderFolder<QuestEventChallenge> {
|
||||
public QuestChallengeReader(File deckDir0) {
|
||||
super(deckDir0, QuestEventChallenge.FN_GET_ID);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QuestEventChallenge read(File file) {
|
||||
final Map<String, List<String>> contents = FileSection.parseSections(FileUtil.readFile(file));
|
||||
final QuestEventChallenge qc = new QuestEventChallenge();
|
||||
|
||||
// Unique properties
|
||||
FileSection sectionQuest = FileSection.parse(contents.get("quest"), "=");
|
||||
qc.setId(sectionQuest.get("ID", "-1"));
|
||||
qc.setOpponent(sectionQuest.get("OpponentName"));
|
||||
qc.setRepeatable(sectionQuest.getBoolean("Repeat", false));
|
||||
qc.setAiLife(sectionQuest.getInt("AILife", 25));
|
||||
qc.setWinsReqd(sectionQuest.getInt("Wins", 20));
|
||||
qc.setCreditsReward(sectionQuest.getInt("Credit Reward", 100));
|
||||
qc.setCardReward(sectionQuest.get("Card Reward"));
|
||||
qc.setHumanExtraCards(Arrays.asList(TextUtil.split(sectionQuest.get("HumanExtras", ""), '|')));
|
||||
qc.setAiExtraCards(Arrays.asList(TextUtil.split(sectionQuest.get("AIExtras", ""), '|')));
|
||||
// Less common properties
|
||||
int humanLife = sectionQuest.getInt("HumanLife", 0);
|
||||
if (humanLife != 0) {
|
||||
qc.setHumanLife(humanLife);
|
||||
}
|
||||
qc.setUseBazaar(sectionQuest.getBoolean("UseBazaar", true));
|
||||
qc.setForceAnte(sectionQuest.contains("ForceAnte") ? sectionQuest.getBoolean("ForceAnte") : null);
|
||||
|
||||
String humanDeck = sectionQuest.get("HumanDeck", null);
|
||||
if (humanDeck != null) {
|
||||
File humanFile = new File(Constants.DEFAULT_CHALLENGES_DIR, humanDeck); // Won't work in other worlds!
|
||||
qc.setHumanDeck(DeckSerializer.fromFile(humanFile));
|
||||
}
|
||||
|
||||
// Common properties
|
||||
FileSection sectionMeta = FileSection.parse(contents.get("metadata"), "=");
|
||||
qc.setTitle(sectionMeta.get("Title"));
|
||||
qc.setName(qc.getTitle()); // Challenges have unique titles
|
||||
qc.setDifficulty(QuestEventDifficulty.fromString(sectionMeta.get("Difficulty")));
|
||||
qc.setDescription(sectionMeta.get("Description"));
|
||||
qc.setIconImageKey(ImageKeys.ICON_PREFIX + sectionMeta.get("Icon"));
|
||||
|
||||
// Deck
|
||||
qc.setEventDeck(DeckSerializer.fromSections(contents));
|
||||
return qc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FilenameFilter getFileFilter() {
|
||||
return DeckStorage.DCK_FILE_FILTER;
|
||||
}
|
||||
}
|
||||
673
forge-m-base/src/forge/quest/io/QuestDataIO.java
Normal file
673
forge-m-base/src/forge/quest/io/QuestDataIO.java
Normal file
@@ -0,0 +1,673 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.io;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.converters.Converter;
|
||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
|
||||
import forge.card.CardEdition;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckSection;
|
||||
import forge.error.BugReporter;
|
||||
import forge.item.*;
|
||||
import forge.model.FModel;
|
||||
import forge.quest.QuestController;
|
||||
import forge.quest.QuestMode;
|
||||
import forge.quest.bazaar.QuestItemType;
|
||||
import forge.quest.data.*;
|
||||
import forge.util.ItemPool;
|
||||
import forge.utils.Constants;
|
||||
import forge.utils.IgnoringXStream;
|
||||
import forge.utils.XmlUtil;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.w3c.dom.*;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* QuestDataIO class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: QuestDataIO.java 24769 2014-02-09 13:56:04Z Hellfish $
|
||||
*/
|
||||
public class QuestDataIO {
|
||||
|
||||
/**
|
||||
* Gets the serializer.
|
||||
*
|
||||
* @param isIgnoring the is ignoring
|
||||
* @return the serializer
|
||||
*/
|
||||
protected static XStream getSerializer(final boolean isIgnoring) {
|
||||
final XStream xStream = isIgnoring ? new IgnoringXStream() : new XStream();
|
||||
xStream.registerConverter(new ItemPoolToXml());
|
||||
xStream.registerConverter(new DeckToXml());
|
||||
xStream.registerConverter(new GameFormatQuestToXml());
|
||||
xStream.registerConverter(new QuestModeToXml());
|
||||
xStream.autodetectAnnotations(true);
|
||||
xStream.alias("CardPool", ItemPool.class);
|
||||
xStream.alias("DeckSection", CardPool.class);
|
||||
return xStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* loadData.
|
||||
* </p>
|
||||
*
|
||||
* @param xmlSaveFile
|
||||
*   {@link java.io.File}
|
||||
* @return {@link forge.quest.data.QuestData}
|
||||
*/
|
||||
public static QuestData loadData(final File xmlSaveFile) {
|
||||
try {
|
||||
QuestData data = null;
|
||||
|
||||
final GZIPInputStream zin = new GZIPInputStream(new FileInputStream(xmlSaveFile));
|
||||
final StringBuilder xml = new StringBuilder();
|
||||
final char[] buf = new char[1024];
|
||||
final InputStreamReader reader = new InputStreamReader(zin);
|
||||
while (reader.ready()) {
|
||||
final int len = reader.read(buf);
|
||||
if (len == -1) {
|
||||
break;
|
||||
} // when end of stream was reached
|
||||
xml.append(buf, 0, len);
|
||||
}
|
||||
|
||||
zin.close();
|
||||
|
||||
String bigXML = xml.toString();
|
||||
data = (QuestData) QuestDataIO.getSerializer(true).fromXML(bigXML);
|
||||
|
||||
if (data.getVersionNumber() != QuestData.CURRENT_VERSION_NUMBER) {
|
||||
try {
|
||||
QuestDataIO.updateSaveFile(data, bigXML, xmlSaveFile.getName().replace(".dat", ""));
|
||||
} catch (final Exception e) {
|
||||
forge.error.BugReporter.reportException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
BugReporter.reportException(ex, "Error loading Quest Data");
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void setFinalField(final Class<T> clasz, final String fieldName, final T instance,
|
||||
final Object newValue) throws IllegalAccessException, NoSuchFieldException {
|
||||
final Field field = clasz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
field.set(instance, newValue); // no difference here (used only to set
|
||||
// initial lives)
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* updateSaveFile.
|
||||
* </p>
|
||||
*
|
||||
* @param newData
|
||||
* a {@link forge.quest.data.QuestData} object.
|
||||
* @param input
|
||||
* a {@link java.lang.String} object.
|
||||
* @throws ParserConfigurationException
|
||||
* @throws IOException
|
||||
* @throws SAXException
|
||||
* @throws NoSuchFieldException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
private static void updateSaveFile(final QuestData newData, final String input, String filename) throws ParserConfigurationException, SAXException, IOException, IllegalAccessException, NoSuchFieldException {
|
||||
final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
final InputSource is = new InputSource();
|
||||
is.setCharacterStream(new StringReader(input));
|
||||
final Document document = builder.parse(is);
|
||||
|
||||
final int saveVersion = newData.getVersionNumber();
|
||||
|
||||
if (saveVersion < 3) {
|
||||
QuestDataIO.setFinalField(QuestData.class, "assets", newData, new QuestAssets(null));
|
||||
|
||||
final int diffIdx = Integer.parseInt(document.getElementsByTagName("diffIndex").item(0).getTextContent());
|
||||
QuestDataIO.setFinalField(QuestData.class, "achievements", newData, new QuestAchievements(diffIdx));
|
||||
}
|
||||
|
||||
if (saveVersion < 4) {
|
||||
QuestDataIO.setFinalField(QuestAssets.class, "inventoryItems", newData.getAssets(), new EnumMap<QuestItemType, Integer>(QuestItemType.class));
|
||||
}
|
||||
|
||||
if (saveVersion < 5) {
|
||||
QuestDataIO.setFinalField(QuestAssets.class, "combatPets", newData.getAssets(), new HashMap<String, QuestItemCondition>());
|
||||
}
|
||||
|
||||
if (saveVersion < 6) {
|
||||
QuestDataIO.setFinalField(QuestData.class, "petSlots", newData, new HashMap<Integer, String>());
|
||||
}
|
||||
|
||||
if(saveVersion < 8) {
|
||||
QuestDataIO.setFinalField(QuestData.class, "isCharmActive", newData, false);
|
||||
}
|
||||
|
||||
final QuestAssets qS = newData.getAssets();
|
||||
final QuestAchievements qA = newData.getAchievements();
|
||||
|
||||
switch (saveVersion) {
|
||||
// There should be a fall-through between the cases so that each
|
||||
// version's changes get applied progressively
|
||||
case 0:
|
||||
// First beta release with new file format,
|
||||
// inventory needs to be migrated
|
||||
QuestDataIO.setFinalField(QuestAssets.class, "inventoryItems", newData.getAssets(), new EnumMap<QuestItemType, Integer>(QuestItemType.class));
|
||||
qS.setItemLevel(QuestItemType.ESTATES, Integer.parseInt(document.getElementsByTagName("estatesLevel").item(0).getTextContent()));
|
||||
qS.setItemLevel(QuestItemType.LUCKY_COIN, Integer.parseInt(document.getElementsByTagName("luckyCoinLevel").item(0).getTextContent()));
|
||||
qS.setItemLevel(QuestItemType.SLEIGHT, Integer.parseInt(document.getElementsByTagName("sleightOfHandLevel").item(0).getTextContent()));
|
||||
|
||||
final int gearLevel = Integer.parseInt(document.getElementsByTagName("gearLevel").item(0).getTextContent());
|
||||
if (gearLevel >= 1) {
|
||||
newData.getAssets().setItemLevel(QuestItemType.MAP, 1);
|
||||
}
|
||||
if (gearLevel == 2) {
|
||||
newData.getAssets().setItemLevel(QuestItemType.ZEPPELIN, 1);
|
||||
}
|
||||
// fall-through
|
||||
case 1:
|
||||
// nothing to do here, everything is managed by CardPoolToXml
|
||||
// deserializer
|
||||
|
||||
case 2:
|
||||
// questdata was divided into assets and achievements
|
||||
if (StringUtils.isBlank(newData.getName())) {
|
||||
QuestDataIO.setFinalField(QuestData.class, "name", newData, filename);
|
||||
}
|
||||
|
||||
QuestDataIO.setFinalField(QuestAchievements.class, "win", qA, Integer.parseInt(document.getElementsByTagName("win").item(0).getTextContent()));
|
||||
QuestDataIO.setFinalField(QuestAchievements.class, "lost", qA, Integer.parseInt(document.getElementsByTagName("lost").item(0).getTextContent()));
|
||||
|
||||
Node nw;
|
||||
if ((nw = document.getElementsByTagName("winstreakBest").item(0)) != null) {
|
||||
QuestDataIO.setFinalField(QuestAchievements.class, "winstreakBest", qA, Integer.parseInt(nw.getTextContent()));
|
||||
}
|
||||
if ((nw = document.getElementsByTagName("winstreakCurrent").item(0)) != null) {
|
||||
QuestDataIO.setFinalField(QuestAchievements.class, "winstreakCurrent", qA, Integer.parseInt(nw.getTextContent()));
|
||||
}
|
||||
|
||||
QuestDataIO.setFinalField(QuestAchievements.class, "challengesPlayed", qA, Integer.parseInt(document.getElementsByTagName("challengesPlayed").item(0).getTextContent()));
|
||||
|
||||
final ArrayList<Integer> completedChallenges = new ArrayList<Integer>();
|
||||
QuestDataIO.setFinalField(QuestAchievements.class, "completedChallenges", qA, completedChallenges);
|
||||
|
||||
if ((nw = document.getElementsByTagName("completedChallenges").item(0)) != null) {
|
||||
final NodeList ccs = nw.getChildNodes();
|
||||
for (int iN = 0; iN < ccs.getLength(); iN++) {
|
||||
final Node n0 = ccs.item(iN);
|
||||
if (n0.getNodeType() != Node.ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
completedChallenges.add(Integer.parseInt(n0.getTextContent()));
|
||||
}
|
||||
}
|
||||
|
||||
final XStream xs = QuestDataIO.getSerializer(true);
|
||||
|
||||
QuestDataIO.setFinalField(QuestAssets.class, "credits", qS, Integer.parseInt(document.getElementsByTagName("credits").item(0).getTextContent()));
|
||||
QuestDataIO.setFinalField(QuestAssets.class, "cardPool", qS, QuestDataIO.readAsset(xs, document, "cardPool", ItemPool.class));
|
||||
QuestDataIO.setFinalField(QuestAssets.class, "myDecks", qS, QuestDataIO.readAsset(xs, document, "myDecks", HashMap.class));
|
||||
QuestDataIO.setFinalField(QuestAssets.class, "shopList", qS, QuestDataIO.readAsset(xs, document, "shopList", ItemPool.class));
|
||||
QuestDataIO.setFinalField(QuestAssets.class, "newCardList", qS, QuestDataIO.readAsset(xs, document, "newCardList", ItemPool.class));
|
||||
|
||||
case 3:
|
||||
// QuestInventory class no longer exists - KV pairs of
|
||||
// QuestItemPair => level moved to assets
|
||||
final Node oldInventory = saveVersion > 0 ? document.getElementsByTagName("inventory").item(1) : null;
|
||||
if (null != oldInventory) {
|
||||
for (int iN = 0; iN < oldInventory.getChildNodes().getLength(); iN++) {
|
||||
final Node _n = oldInventory.getChildNodes().item(iN);
|
||||
if (_n.getNodeType() != Node.ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
final Element n = (Element) _n;
|
||||
final String name = n.getElementsByTagName("string").item(0).getTextContent();
|
||||
final QuestItemType qType = QuestItemType.valueFromSaveKey(name);
|
||||
int level = 0;
|
||||
for (int iX = 0; iX < n.getChildNodes().getLength(); iX++) {
|
||||
final Node _x = n.getChildNodes().item(iX);
|
||||
if (_x.getNodeType() != Node.ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
final Element x = (Element) _x;
|
||||
if (!x.getTagName().startsWith("forge.quest.data.")) {
|
||||
continue;
|
||||
}
|
||||
final String sLevel = x.getElementsByTagName("level").item(0).getTextContent();
|
||||
if (StringUtils.isNotBlank(sLevel)) {
|
||||
level = Integer.parseInt(sLevel);
|
||||
}
|
||||
}
|
||||
qS.setItemLevel(qType, level);
|
||||
}
|
||||
}
|
||||
|
||||
case 4:
|
||||
if (saveVersion > 0) {
|
||||
NodeList pets = document.getElementsByTagName("pets").item(0).getChildNodes();
|
||||
for (int i = 0; i < pets.getLength(); i++) {
|
||||
if (pets.item(i).getNodeType() != Node.ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
final Element entry = (Element) pets.item(i);
|
||||
String name = entry.getElementsByTagName("string").item(0).getTextContent();
|
||||
String sLevel = entry.getElementsByTagName("level").item(0).getTextContent();
|
||||
qS.setPetLevel(name, Integer.parseInt(sLevel));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// pet manager will be re-engineered here
|
||||
|
||||
case 6:
|
||||
// have to convert completed challenges list members to strings.
|
||||
for(int i = qA.getLockedChallenges().size()-1; i >= 0; i-- ) {
|
||||
Object lc = qA.getLockedChallenges().get(i);
|
||||
if (!(lc instanceof String))
|
||||
qA.getLockedChallenges().set(i, lc.toString());
|
||||
}
|
||||
for(int i = qA.getCurrentChallenges().size()-1; i >= 0; i-- ) {
|
||||
Object lc = qA.getCurrentChallenges().get(i);
|
||||
if (!(lc instanceof String))
|
||||
qA.getCurrentChallenges().set(i, lc.toString());
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// mark the QD as the latest version
|
||||
newData.setVersionNumber(QuestData.CURRENT_VERSION_NUMBER);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T readAsset(final XStream xs, final Document doc, final String tagName, final Class<T> clasz)
|
||||
throws IllegalAccessException, NoSuchFieldException {
|
||||
final NodeList nn = doc.getElementsByTagName(tagName);
|
||||
final Node n = nn.item(0);
|
||||
|
||||
final Attr att = doc.createAttribute("resolves-to");
|
||||
att.setValue(clasz.getCanonicalName());
|
||||
n.getAttributes().setNamedItem(att);
|
||||
|
||||
final String xmlData = XmlUtil.nodeToString(n);
|
||||
return (T) xs.fromXML(xmlData);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* saveData.
|
||||
* </p>
|
||||
*
|
||||
* @param qd
|
||||
* a {@link forge.quest.data.QuestData} object.
|
||||
*/
|
||||
public static synchronized void saveData(final QuestData qd) {
|
||||
try {
|
||||
final XStream xStream = QuestDataIO.getSerializer(false);
|
||||
|
||||
final File f = new File(Constants.QUEST_SAVE_DIR, qd.getName());
|
||||
QuestDataIO.savePacked(f + ".dat", xStream, qd);
|
||||
// QuestDataIO.saveUnpacked(f + ".xml", xStream, qd);
|
||||
|
||||
}
|
||||
catch (final Exception ex) {
|
||||
BugReporter.reportException(ex, "Error saving Quest Data.");
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void savePacked(final String f, final XStream xStream, final QuestData qd) throws IOException {
|
||||
final BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(f));
|
||||
final GZIPOutputStream zout = new GZIPOutputStream(bout);
|
||||
xStream.toXML(qd, zout);
|
||||
zout.flush();
|
||||
zout.close();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused") // used only for debug purposes
|
||||
private static void saveUnpacked(final String f, final XStream xStream, final QuestData qd) throws IOException {
|
||||
final BufferedOutputStream boutUnp = new BufferedOutputStream(new FileOutputStream(f));
|
||||
xStream.toXML(qd, boutUnp);
|
||||
boutUnp.flush();
|
||||
boutUnp.close();
|
||||
}
|
||||
|
||||
private static class GameFormatQuestToXml implements Converter {
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean canConvert(final Class clasz) {
|
||||
return clasz.equals(GameFormatQuest.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
|
||||
|
||||
writer.startNode("format");
|
||||
GameFormatQuest format = (GameFormatQuest) source;
|
||||
writer.addAttribute("name", format.getName());
|
||||
writer.addAttribute("unlocksUsed", Integer.toString(format.getUnlocksUsed()));
|
||||
writer.addAttribute("canUnlock", format.canUnlockSets() ? "1" : "0");
|
||||
writer.endNode();
|
||||
|
||||
for (String set : format.getAllowedSetCodes()) {
|
||||
writer.startNode("set");
|
||||
writer.addAttribute("s", set);
|
||||
writer.endNode();
|
||||
}
|
||||
for (String ban : format.getBannedCardNames()) {
|
||||
writer.startNode("ban");
|
||||
writer.addAttribute("s", ban);
|
||||
writer.endNode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
|
||||
reader.moveDown();
|
||||
String name = reader.getAttribute("name");
|
||||
String unlocksUsed = reader.getAttribute("unlocksUsed");
|
||||
boolean canUnlock = !("0".equals(reader.getAttribute("canUnlock")));
|
||||
List<String> allowedSets = new ArrayList<String>();
|
||||
List<String> bannedCards = new ArrayList<String>();
|
||||
reader.moveUp();
|
||||
while (reader.hasMoreChildren()) {
|
||||
reader.moveDown();
|
||||
final String nodename = reader.getNodeName();
|
||||
if (nodename.equals("ban")) {
|
||||
bannedCards.add(reader.getAttribute("s"));
|
||||
// System.out.println("Added + " + toBan + " to banned cards");
|
||||
}
|
||||
else if (nodename.equals("set")) {
|
||||
allowedSets.add(reader.getAttribute("s"));
|
||||
// System.out.println("Added + " + toSets + " to legal sets");
|
||||
}
|
||||
reader.moveUp();
|
||||
}
|
||||
GameFormatQuest res = new GameFormatQuest(name, allowedSets, bannedCards);
|
||||
try {
|
||||
if (StringUtils.isNotEmpty(unlocksUsed)) {
|
||||
setFinalField(GameFormatQuest.class, "unlocksUsed", res, Integer.parseInt(unlocksUsed));
|
||||
}
|
||||
setFinalField(GameFormatQuest.class, "allowUnlocks", res, canUnlock);
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
private static class QuestModeToXml implements Converter {
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean canConvert(final Class clasz) {
|
||||
return clasz.equals(QuestMode.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
|
||||
QuestMode mode = (QuestMode) source;
|
||||
String sMode = mode.toString();
|
||||
writer.setValue(sMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
|
||||
final String value = reader.getValue();
|
||||
return QuestMode.smartValueOf(value, QuestMode.Classic);
|
||||
}
|
||||
}
|
||||
|
||||
private static class DeckToXml extends ItemPoolToXml {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.thoughtworks.xstream.converters.ConverterMatcher#canConvert(java.lang.Class)
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean canConvert(Class type) {
|
||||
return type.equals(Deck.class);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.thoughtworks.xstream.converters.Converter#marshal(java.lang.Object, com.thoughtworks.xstream.io.HierarchicalStreamWriter, com.thoughtworks.xstream.converters.MarshallingContext)
|
||||
*/
|
||||
@Override
|
||||
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
|
||||
Deck d = (Deck)source;
|
||||
writer.startNode("name");
|
||||
writer.setValue(d.getName());
|
||||
writer.endNode();
|
||||
|
||||
for( Entry<DeckSection, CardPool> ds : d ) {
|
||||
writer.startNode(ds.getKey().toString());
|
||||
for (final Entry<PaperCard, Integer> e : ds.getValue()) {
|
||||
this.write(e.getKey(), e.getValue(), writer);
|
||||
}
|
||||
writer.endNode();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.thoughtworks.xstream.converters.Converter#unmarshal(com.thoughtworks.xstream.io.HierarchicalStreamReader, com.thoughtworks.xstream.converters.UnmarshallingContext)
|
||||
*/
|
||||
@Override
|
||||
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
|
||||
|
||||
reader.moveDown(); // <name> tag MUST be at first position at all times
|
||||
String deckName = reader.getValue();
|
||||
reader.moveUp();
|
||||
|
||||
final Deck result = new Deck(deckName);
|
||||
|
||||
while (reader.hasMoreChildren()) {
|
||||
reader.moveDown();
|
||||
DeckSection section = DeckSection.smartValueOf(reader.getNodeName());
|
||||
if ( null == section )
|
||||
throw new RuntimeException("Quest deck has unknown section: " + reader.getNodeName());
|
||||
|
||||
CardPool pool = result.getOrCreate(section);
|
||||
while (reader.hasMoreChildren()) {
|
||||
reader.moveDown();
|
||||
final String sCnt = reader.getAttribute("n");
|
||||
final int cnt = StringUtils.isNumeric(sCnt) ? Integer.parseInt(sCnt) : 1;
|
||||
final String nodename = reader.getNodeName();
|
||||
if ("string".equals(nodename)) {
|
||||
pool.add(FModel.getMagicDb().getCommonCards().getCard(reader.getValue()));
|
||||
} else if ("card".equals(nodename)) { // new format
|
||||
pool.add(this.readCardPrinted(reader), cnt);
|
||||
}
|
||||
reader.moveUp();
|
||||
}
|
||||
reader.moveUp();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ItemPoolToXml implements Converter {
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean canConvert(final Class clasz) {
|
||||
return clasz.equals(ItemPool.class);
|
||||
}
|
||||
|
||||
protected void write(final PaperCard cref, final Integer count, final HierarchicalStreamWriter writer) {
|
||||
writer.startNode("card");
|
||||
writer.addAttribute("c", cref.getName());
|
||||
writer.addAttribute("s", cref.getEdition());
|
||||
if (cref.isFoil()) {
|
||||
writer.addAttribute("foil", "1");
|
||||
}
|
||||
writer.addAttribute("i", Integer.toString(cref.getArtIndex()));
|
||||
writer.addAttribute("n", count.toString());
|
||||
writer.endNode();
|
||||
}
|
||||
|
||||
protected void write(final BoosterPack booster, final Integer count, final HierarchicalStreamWriter writer) {
|
||||
writer.startNode("booster");
|
||||
writer.addAttribute("s", booster.getEdition());
|
||||
writer.addAttribute("n", count.toString());
|
||||
writer.endNode();
|
||||
}
|
||||
|
||||
protected void write(final FatPack fatpack, final Integer count, final HierarchicalStreamWriter writer) {
|
||||
writer.startNode("fpack");
|
||||
writer.addAttribute("s", fatpack.getEdition());
|
||||
writer.addAttribute("n", count.toString());
|
||||
writer.endNode();
|
||||
}
|
||||
|
||||
protected void write(final TournamentPack booster, final Integer count, final HierarchicalStreamWriter writer) {
|
||||
writer.startNode("tpack");
|
||||
writer.addAttribute("s", booster.getEdition());
|
||||
writer.addAttribute("n", count.toString());
|
||||
writer.endNode();
|
||||
}
|
||||
|
||||
protected void write(final PreconDeck deck, final Integer count, final HierarchicalStreamWriter writer) {
|
||||
writer.startNode("precon");
|
||||
writer.addAttribute("name", deck.getName());
|
||||
writer.addAttribute("n", count.toString());
|
||||
writer.endNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final ItemPool<InventoryItem> pool = (ItemPool<InventoryItem>) source;
|
||||
for (final Entry<InventoryItem, Integer> e : pool) {
|
||||
final InventoryItem item = e.getKey();
|
||||
final Integer count = e.getValue();
|
||||
if (item instanceof PaperCard) {
|
||||
this.write((PaperCard) item, count, writer);
|
||||
} else if (item instanceof BoosterPack) {
|
||||
this.write((BoosterPack) item, count, writer);
|
||||
} else if (item instanceof TournamentPack) {
|
||||
this.write((TournamentPack) item, count, writer);
|
||||
} else if (item instanceof FatPack) {
|
||||
this.write((FatPack) item, count, writer);
|
||||
} else if (item instanceof PreconDeck) {
|
||||
this.write((PreconDeck) item, count, writer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
|
||||
final ItemPool<InventoryItem> result = new ItemPool<InventoryItem>(InventoryItem.class);
|
||||
while (reader.hasMoreChildren()) {
|
||||
reader.moveDown();
|
||||
final String sCnt = reader.getAttribute("n");
|
||||
final int cnt = StringUtils.isNumeric(sCnt) ? Integer.parseInt(sCnt) : 1;
|
||||
final String nodename = reader.getNodeName();
|
||||
|
||||
if ("string".equals(nodename)) {
|
||||
result.add(FModel.getMagicDb().getCommonCards().getCard(reader.getValue()));
|
||||
} else if ("card".equals(nodename)) { // new format
|
||||
result.add(this.readCardPrinted(reader), cnt);
|
||||
} else if ("booster".equals(nodename)) {
|
||||
result.add(this.readBooster(reader), cnt);
|
||||
} else if ("tpack".equals(nodename)) {
|
||||
result.add(this.readTournamentPack(reader), cnt);
|
||||
} else if ("fpack".equals(nodename)) {
|
||||
result.add(this.readFatPack(reader), cnt);
|
||||
} else if ("precon".equals(nodename)) {
|
||||
final PreconDeck toAdd = this.readPreconDeck(reader);
|
||||
if (null != toAdd) {
|
||||
result.add(toAdd, cnt);
|
||||
}
|
||||
}
|
||||
reader.moveUp();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected PreconDeck readPreconDeck(final HierarchicalStreamReader reader) {
|
||||
String name = reader.getAttribute("name");
|
||||
if (name == null) {
|
||||
name = reader.getAttribute("s");
|
||||
}
|
||||
return QuestController.getPrecons().get(name);
|
||||
}
|
||||
|
||||
protected BoosterPack readBooster(final HierarchicalStreamReader reader) {
|
||||
final CardEdition ed = FModel.getMagicDb().getEditions().get(reader.getAttribute("s"));
|
||||
return BoosterPack.FN_FROM_SET.apply(ed);
|
||||
}
|
||||
|
||||
protected TournamentPack readTournamentPack(final HierarchicalStreamReader reader) {
|
||||
final CardEdition ed = FModel.getMagicDb().getEditions().get(reader.getAttribute("s"));
|
||||
return TournamentPack.FN_FROM_SET.apply(ed);
|
||||
}
|
||||
|
||||
protected FatPack readFatPack(final HierarchicalStreamReader reader) {
|
||||
final CardEdition ed = FModel.getMagicDb().getEditions().get(reader.getAttribute("s"));
|
||||
return FatPack.FN_FROM_SET.apply(ed);
|
||||
}
|
||||
|
||||
protected PaperCard readCardPrinted(final HierarchicalStreamReader reader) {
|
||||
final String name = reader.getAttribute("c");
|
||||
final String set = reader.getAttribute("s");
|
||||
final String sIndex = reader.getAttribute("i");
|
||||
final short index = StringUtils.isNumeric(sIndex) ? Short.parseShort(sIndex) : 0;
|
||||
final boolean foil = "1".equals(reader.getAttribute("foil"));
|
||||
PaperCard c = FModel.getMagicDb().getCommonCards().getCard(name, set, index);
|
||||
if ( null == c ) c = FModel.getMagicDb().getCommonCards().getCard(name);
|
||||
return foil ? FModel.getMagicDb().getCommonCards().getFoiled(c) : c;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
forge-m-base/src/forge/quest/io/QuestDuelReader.java
Normal file
47
forge-m-base/src/forge/quest/io/QuestDuelReader.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package forge.quest.io;
|
||||
|
||||
import forge.ImageKeys;
|
||||
import forge.deck.io.DeckSerializer;
|
||||
import forge.deck.io.DeckStorage;
|
||||
import forge.quest.QuestEvent;
|
||||
import forge.quest.QuestEventDifficulty;
|
||||
import forge.quest.QuestEventDuel;
|
||||
import forge.util.FileSection;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.storage.StorageReaderFolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class QuestDuelReader extends StorageReaderFolder<QuestEventDuel> {
|
||||
public QuestDuelReader(File deckDir0) {
|
||||
super(deckDir0, QuestEvent.FN_GET_NAME);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QuestEventDuel read(File file) {
|
||||
final Map<String, List<String>> contents = FileSection.parseSections(FileUtil.readFile(file));
|
||||
final QuestEventDuel qc = new QuestEventDuel();
|
||||
|
||||
// Common properties
|
||||
FileSection sectionMeta = FileSection.parse(contents.get("metadata"), "=");
|
||||
qc.setTitle(sectionMeta.get("Title"));
|
||||
qc.setName(sectionMeta.get("Name")); // Challenges have unique titles
|
||||
qc.setDifficulty(QuestEventDifficulty.fromString(sectionMeta.get("Difficulty")));
|
||||
qc.setDescription(sectionMeta.get("Description"));
|
||||
qc.setCardReward(sectionMeta.get("Card Reward"));
|
||||
qc.setIconImageKey(ImageKeys.ICON_PREFIX + sectionMeta.get("Icon"));
|
||||
|
||||
// Deck
|
||||
qc.setEventDeck(DeckSerializer.fromSections(contents));
|
||||
return qc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FilenameFilter getFileFilter() {
|
||||
return DeckStorage.DCK_FILE_FILTER;
|
||||
}
|
||||
}
|
||||
132
forge-m-base/src/forge/quest/io/ReadPriceList.java
Normal file
132
forge-m-base/src/forge/quest/io/ReadPriceList.java
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.quest.io;
|
||||
|
||||
import forge.card.MagicColor;
|
||||
import forge.error.BugReporter;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.MyRandom;
|
||||
import forge.utils.Constants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* ReadPriceList class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: ReadPriceList.java 24769 2014-02-09 13:56:04Z Hellfish $
|
||||
*/
|
||||
public class ReadPriceList {
|
||||
|
||||
/** Constant <code>comment="//"</code>. */
|
||||
private static final String COMMENT = "//";
|
||||
|
||||
private HashMap<String, Integer> priceMap;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for ReadPriceList.
|
||||
* </p>
|
||||
*/
|
||||
public ReadPriceList() {
|
||||
this.setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* setup.
|
||||
* </p>
|
||||
*/
|
||||
private void setup() {
|
||||
this.priceMap = this.readFile(Constants.QUEST_CARD_PRICE_FILE);
|
||||
this.priceMap.putAll(this.readFile(Constants.PRICES_BOOSTER_FILE));
|
||||
|
||||
} // setup()
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* readFile.
|
||||
* </p>
|
||||
*
|
||||
* @param file
|
||||
* a {@link java.io.File} object.
|
||||
* @return a {@link java.util.HashMap} object.
|
||||
*/
|
||||
private HashMap<String, Integer> readFile(String file) {
|
||||
final HashMap<String, Integer> map = new HashMap<String, Integer>();
|
||||
final Random r = MyRandom.getRandom();
|
||||
|
||||
List<String> lines = FileUtil.readFile(file);
|
||||
for (String line : lines) {
|
||||
if (line.trim().length() == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (line.startsWith(ReadPriceList.COMMENT)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String[] s = line.split("=");
|
||||
final String name = s[0].trim();
|
||||
final String price = s[1].trim();
|
||||
|
||||
try {
|
||||
int val = Integer.parseInt(price.trim());
|
||||
|
||||
if (!(MagicColor.Constant.BASIC_LANDS.contains(name) || MagicColor.Constant.SNOW_LANDS.contains(name))) {
|
||||
float ff = 0;
|
||||
if (r.nextInt(100) < 90) {
|
||||
ff = r.nextInt(10) * (float) .01;
|
||||
} else {
|
||||
// +/- 50%
|
||||
ff = r.nextInt(50) * (float) .01;
|
||||
}
|
||||
|
||||
if (r.nextInt(100) < 50) {
|
||||
val = (int) (val * (1 - ff));
|
||||
} else {
|
||||
// +ff%
|
||||
val = (int) (val * (1 + ff));
|
||||
}
|
||||
}
|
||||
|
||||
map.put(name, val);
|
||||
}
|
||||
catch (final NumberFormatException nfe) {
|
||||
BugReporter.reportBug("NumberFormatException: " + nfe.getMessage());
|
||||
}
|
||||
}
|
||||
return map;
|
||||
} // readFile()
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getPriceList.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link java.util.Map} object.
|
||||
*/
|
||||
public final Map<String, Integer> getPriceList() {
|
||||
return this.priceMap;
|
||||
}
|
||||
}
|
||||
3
forge-m-base/src/forge/quest/io/package-info.java
Normal file
3
forge-m-base/src/forge/quest/io/package-info.java
Normal file
@@ -0,0 +1,3 @@
|
||||
/** Forge Card Game. */
|
||||
package forge.quest.io;
|
||||
|
||||
3
forge-m-base/src/forge/quest/package-info.java
Normal file
3
forge-m-base/src/forge/quest/package-info.java
Normal file
@@ -0,0 +1,3 @@
|
||||
/** Forge Card Game. */
|
||||
package forge.quest;
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
package forge.screens.constructed;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Vector;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.Forge;
|
||||
import forge.Forge.Graphics;
|
||||
import forge.assets.FSkin;
|
||||
import forge.assets.FSkinColor;
|
||||
@@ -24,17 +16,20 @@ import forge.assets.FSkinImage;
|
||||
import forge.assets.FTextureRegionImage;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.deck.DeckSection;
|
||||
import forge.deck.DeckType;
|
||||
import forge.deck.DeckgenUtil;
|
||||
import forge.deck.FDeckChooser;
|
||||
import forge.game.GameType;
|
||||
import forge.game.player.LobbyPlayer;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
import forge.game.player.LobbyPlayer.PlayerType;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.CardCollections;
|
||||
import forge.model.FModel;
|
||||
import forge.net.FServer;
|
||||
import forge.net.Lobby;
|
||||
import forge.screens.FScreen;
|
||||
import forge.screens.LaunchScreen;
|
||||
import forge.toolbox.FCheckBox;
|
||||
import forge.toolbox.FComboBox;
|
||||
@@ -48,6 +43,7 @@ import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.FScrollPane;
|
||||
import forge.toolbox.FTextField;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.Lang;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.NameGenerator;
|
||||
import forge.util.storage.IStorage;
|
||||
@@ -94,15 +90,10 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
private final List<FLabel> closePlayerBtnList = new ArrayList<FLabel>(6);
|
||||
private final FLabel addPlayerBtn = new FLabel.ButtonBuilder().fontSize(14).text("Add a Player").build();
|
||||
|
||||
private final List<FDeckChooser> deckChoosers = new ArrayList<FDeckChooser>(8);
|
||||
private final FCheckBox cbSingletons = new FCheckBox("Singleton Mode");
|
||||
private final FCheckBox cbArtifacts = new FCheckBox("Remove Artifacts");
|
||||
|
||||
// Variants
|
||||
private final List<DeckList> schemeDeckLists = new ArrayList<DeckList>();
|
||||
private final List<DeckList> commanderDeckLists = new ArrayList<DeckList>();
|
||||
private final List<DeckList> planarDeckLists = new ArrayList<DeckList>();
|
||||
private final List<DeckList> vgdAvatarLists = new ArrayList<DeckList>();
|
||||
private final List<PaperCard> vgdAllAvatars = new ArrayList<PaperCard>();
|
||||
private final List<PaperCard> vgdAllAiAvatars = new ArrayList<PaperCard>();
|
||||
private final List<PaperCard> nonRandomHumanAvatars = new ArrayList<PaperCard>();
|
||||
@@ -160,13 +151,36 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
|
||||
add(playersScroll);
|
||||
|
||||
addPlayerBtn.setCommand(new FEventHandler() {
|
||||
getDeckChooser(0).initialize(FPref.CONSTRUCTED_P1_DECK_STATE, DeckType.PRECONSTRUCTED_DECK);
|
||||
getDeckChooser(1).initialize(FPref.CONSTRUCTED_P2_DECK_STATE, DeckType.COLOR_DECK);
|
||||
getDeckChooser(2).initialize(FPref.CONSTRUCTED_P3_DECK_STATE, DeckType.COLOR_DECK);
|
||||
getDeckChooser(3).initialize(FPref.CONSTRUCTED_P4_DECK_STATE, DeckType.COLOR_DECK);
|
||||
getDeckChooser(4).initialize(FPref.CONSTRUCTED_P5_DECK_STATE, DeckType.COLOR_DECK);
|
||||
getDeckChooser(5).initialize(FPref.CONSTRUCTED_P6_DECK_STATE, DeckType.COLOR_DECK);
|
||||
getDeckChooser(6).initialize(FPref.CONSTRUCTED_P7_DECK_STATE, DeckType.COLOR_DECK);
|
||||
getDeckChooser(7).initialize(FPref.CONSTRUCTED_P8_DECK_STATE, DeckType.COLOR_DECK);
|
||||
|
||||
// Checkbox event handling
|
||||
cbSingletons.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
addPlayer();
|
||||
prefs.setPref(FPref.DECKGEN_SINGLETONS, String.valueOf(cbSingletons.isSelected()));
|
||||
prefs.save();
|
||||
}
|
||||
});
|
||||
add(addPlayerBtn);
|
||||
cbArtifacts.setCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
prefs.setPref(FPref.DECKGEN_ARTIFACTS, String.valueOf(cbArtifacts.isSelected()));
|
||||
prefs.save();
|
||||
}
|
||||
});
|
||||
|
||||
// Pre-select checkboxes
|
||||
cbSingletons.setSelected(prefs.getPrefBoolean(FPref.DECKGEN_SINGLETONS));
|
||||
cbArtifacts.setSelected(prefs.getPrefBoolean(FPref.DECKGEN_ARTIFACTS));
|
||||
|
||||
updatePlayersFromPrefs();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -203,35 +217,13 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
}
|
||||
|
||||
public final FDeckChooser getDeckChooser(int playernum) {
|
||||
return deckChoosers.get(playernum);
|
||||
}
|
||||
|
||||
private class DeckList extends FList<Object> {
|
||||
Object selectedValue;
|
||||
|
||||
public Object getSelectedValue() {
|
||||
return selectedValue;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPlayerAI(int playernum) {
|
||||
return playerPanels.get(playernum).getPlayerType() == PlayerType.COMPUTER;
|
||||
return playerPanels.get(playernum).deckChooser;
|
||||
}
|
||||
|
||||
public int getNumPlayers() {
|
||||
return activePlayersNum;
|
||||
}
|
||||
|
||||
public final List<Integer> getParticipants() {
|
||||
final List<Integer> participants = new ArrayList<Integer>(activePlayersNum);
|
||||
for (final PlayerPanel panel : playerPanels) {
|
||||
if (panel.isVisible()) {
|
||||
participants.add(playerPanels.indexOf(panel));
|
||||
}
|
||||
}
|
||||
return participants;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean buildLaunchParams(LaunchParams launchParams) {
|
||||
launchParams.gameType = GameType.Constructed;
|
||||
@@ -241,7 +233,7 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (final int i : getParticipants()) {
|
||||
for (int i = 0; i < activePlayersNum; i++) {
|
||||
if (getDeckChooser(i).getPlayer() == null) {
|
||||
FOptionPane.showMessageDialog("Please specify a deck for " + getPlayerName(i));
|
||||
return false;
|
||||
@@ -253,7 +245,7 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
|
||||
boolean checkLegality = FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY);
|
||||
if (checkLegality && !variantTypes.contains(GameType.Commander)) { //Commander deck replaces regular deck and is checked later
|
||||
for (final int i : getParticipants()) {
|
||||
for (int i = 0; i < activePlayersNum; i++) {
|
||||
String name = getPlayerName(i);
|
||||
String errMsg = GameType.Constructed.getDecksFormat().getDeckConformanceProblem(getDeckChooser(i).getPlayer().getDeck());
|
||||
if (errMsg != null) {
|
||||
@@ -265,11 +257,12 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
|
||||
Lobby lobby = FServer.getLobby();
|
||||
List<RegisteredPlayer> players = new ArrayList<RegisteredPlayer>();
|
||||
for (final int i : getParticipants()) {
|
||||
for (int i = 0; i < activePlayersNum; i++) {
|
||||
PlayerPanel playerPanel = playerPanels.get(i);
|
||||
String name = getPlayerName(i);
|
||||
LobbyPlayer lobbyPlayer = isPlayerAI(i) ? lobby.getAiPlayer(name,
|
||||
LobbyPlayer lobbyPlayer = playerPanel.isPlayerAI() ? lobby.getAiPlayer(name,
|
||||
getPlayerAvatar(i)) : lobby.getGuiPlayer();
|
||||
RegisteredPlayer rp = getDeckChooser(i).getPlayer();
|
||||
RegisteredPlayer rp = playerPanel.deckChooser.getPlayer();
|
||||
|
||||
if (variantTypes.isEmpty()) {
|
||||
rp.setTeamNumber(getTeam(i));
|
||||
@@ -279,7 +272,7 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
Deck deck = null;
|
||||
boolean isCommanderMatch = variantTypes.contains(GameType.Commander);
|
||||
if (isCommanderMatch) {
|
||||
Object selected = commanderDeckLists.get(i).getSelectedValue();
|
||||
Object selected = playerPanel.commanderDeckList.getSelectedValue();
|
||||
if (selected instanceof String) {
|
||||
String sel = (String) selected;
|
||||
IStorage<Deck> comDecks = FModel.getDecks().getCommander();
|
||||
@@ -312,7 +305,7 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
//Archenemy
|
||||
if (variantTypes.contains(GameType.ArchenemyRumble)
|
||||
|| (variantTypes.contains(GameType.Archenemy) && playerIsArchenemy)) {
|
||||
Object selected = schemeDeckLists.get(i).getSelectedValue();
|
||||
Object selected = playerPanel.schemeDeckList.getSelectedValue();
|
||||
CardPool schemePool = null;
|
||||
if (selected instanceof String) {
|
||||
String sel = (String) selected;
|
||||
@@ -347,7 +340,7 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
|
||||
//Planechase
|
||||
if (variantTypes.contains(GameType.Planechase)) {
|
||||
Object selected = planarDeckLists.get(i).getSelectedValue();
|
||||
Object selected = playerPanel.planarDeckList.getSelectedValue();
|
||||
CardPool planePool = null;
|
||||
if (selected instanceof String) {
|
||||
String sel = (String) selected;
|
||||
@@ -381,7 +374,7 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
|
||||
//Vanguard
|
||||
if (variantTypes.contains(GameType.Vanguard)) {
|
||||
Object selected = vgdAvatarLists.get(i).getSelectedValue();
|
||||
Object selected = playerPanel.vgdAvatarList.getSelectedValue();
|
||||
if (selected instanceof String) {
|
||||
String sel = (String) selected;
|
||||
if (sel.contains("Use deck's default avatar") && deck.has(DeckSection.Avatar)) {
|
||||
@@ -448,10 +441,26 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
private final FLabel vgdSelectorBtn = new FLabel.ButtonBuilder().text("Select a Vanguard avatar").build();
|
||||
private final FLabel vgdLabel = newLabel("Vanguard:");
|
||||
|
||||
private final FDeckChooser deckChooser;
|
||||
private final DeckList schemeDeckList, commanderDeckList, planarDeckList, vgdAvatarList;
|
||||
|
||||
public PlayerPanel(final int index0) {
|
||||
super();
|
||||
index = index0;
|
||||
playerIsArchenemy = index == 0;
|
||||
deckChooser = new FDeckChooser(isPlayerAI());
|
||||
deckChooser.initialize();
|
||||
deckChooser.getLstDecks().setSelectCommand(new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
String text = deckChooser.getSelectedDeckType().toString() + ": " + Lang.joinHomogenous(deckChooser.getLstDecks().getSelectedItems(), DeckProxy.FN_GET_NAME);
|
||||
setDeckSelectorButtonText(text);
|
||||
}
|
||||
});
|
||||
schemeDeckList = new DeckList();
|
||||
commanderDeckList = new DeckList();
|
||||
planarDeckList = new DeckList();
|
||||
vgdAvatarList = new DeckList();
|
||||
|
||||
// Add a button to players 3+ to remove them from the setup
|
||||
if (index >= 2) {
|
||||
@@ -502,6 +511,39 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
|
||||
addHandlersToVariantsControls();
|
||||
updateVariantControlsVisibility();
|
||||
|
||||
final CardCollections decks = FModel.getDecks();
|
||||
|
||||
commanderDeckList.list.addItem("Generate");
|
||||
if (decks.getCommander().size() > 0) {
|
||||
commanderDeckList.list.addItem("Random");
|
||||
for (Deck comDeck : decks.getCommander()) {
|
||||
commanderDeckList.list.addItem(comDeck);
|
||||
}
|
||||
}
|
||||
commanderDeckList.setSelectedIndex(0);
|
||||
|
||||
schemeDeckList.list.addItem("Use deck's scheme section (random if unavailable)");
|
||||
schemeDeckList.list.addItem("Generate");
|
||||
if (decks.getScheme().size() > 0) {
|
||||
schemeDeckList.list.addItem("Random");
|
||||
for (Deck schemeDeck : decks.getScheme()) {
|
||||
schemeDeckList.list.addItem(schemeDeck);
|
||||
}
|
||||
}
|
||||
schemeDeckList.setSelectedIndex(0);
|
||||
|
||||
planarDeckList.list.addItem("Use deck's planes section (random if unavailable)");
|
||||
planarDeckList.list.addItem("Generate");
|
||||
if (decks.getPlane().size() > 0) {
|
||||
planarDeckList.list.addItem("Random");
|
||||
for (Deck planarDeck : decks.getPlane()) {
|
||||
planarDeckList.list.addItem(planarDeck);
|
||||
}
|
||||
}
|
||||
planarDeckList.setSelectedIndex(0);
|
||||
|
||||
updateVanguardList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -557,7 +599,7 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
private final FEventHandler humanAiSwitched = new FEventHandler() {
|
||||
@Override
|
||||
public void handleEvent(FEvent e) {
|
||||
updateVanguardList(index);
|
||||
updateVanguardList();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -634,8 +676,8 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
vgdLabel.setVisible(appliedVariants.contains(GameType.Vanguard));
|
||||
}
|
||||
|
||||
public PlayerType getPlayerType() {
|
||||
return humanAiSwitch.isToggled() ? PlayerType.COMPUTER : PlayerType.HUMAN;
|
||||
public boolean isPlayerAI() {
|
||||
return humanAiSwitch.isToggled();
|
||||
}
|
||||
|
||||
public void setVanguardButtonText(String text) {
|
||||
@@ -871,6 +913,79 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
public String getPlayerName() {
|
||||
return txtPlayerName.getText();
|
||||
}
|
||||
|
||||
private void changeDeck(final GameType forGameType) {
|
||||
switch (forGameType) {
|
||||
case Constructed:
|
||||
Forge.openScreen(deckChooser);
|
||||
break;
|
||||
case Archenemy:
|
||||
case ArchenemyRumble:
|
||||
if (playerIsArchenemy) {
|
||||
Forge.openScreen(schemeDeckList);
|
||||
}
|
||||
else {
|
||||
Forge.openScreen(deckChooser);
|
||||
}
|
||||
break;
|
||||
case Commander:
|
||||
Forge.openScreen(commanderDeckList);
|
||||
break;
|
||||
case Planechase:
|
||||
Forge.openScreen(planarDeckList);
|
||||
break;
|
||||
case Vanguard:
|
||||
updateVanguardList();
|
||||
Forge.openScreen(vgdAvatarList);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** update vanguard list. */
|
||||
public void updateVanguardList() {
|
||||
Object lastSelection = vgdAvatarList.getSelectedValue();
|
||||
vgdAvatarList.setSelectedIndex(-1);
|
||||
vgdAvatarList.list.setListData(isPlayerAI() ? aiListData : humanListData);
|
||||
if (lastSelection != null) {
|
||||
vgdAvatarList.setSelectedValue(lastSelection);
|
||||
}
|
||||
if (vgdAvatarList.getSelectedIndex() == -1) {
|
||||
vgdAvatarList.setSelectedIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
private class DeckList extends FScreen {
|
||||
private final FList<Object> list;
|
||||
private int selectedIndex;
|
||||
|
||||
private DeckList() {
|
||||
super(true, "", false);
|
||||
list = new FList<Object>();
|
||||
}
|
||||
|
||||
public int getSelectedIndex() {
|
||||
return selectedIndex;
|
||||
}
|
||||
|
||||
public void setSelectedIndex(int index) {
|
||||
selectedIndex = index;
|
||||
}
|
||||
|
||||
public Object getSelectedValue() {
|
||||
return list.getItemAt(selectedIndex);
|
||||
}
|
||||
|
||||
public void setSelectedValue(Object value) {
|
||||
selectedIndex = list.getIndexOf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLayout(float startY, float width, float height) {
|
||||
list.setBounds(0, startY, width, height - startY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Saves avatar prefs for players one and two. */
|
||||
@@ -961,7 +1076,7 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
int lastTeam = -1;
|
||||
final List<Integer> teamList = appliedVariants.contains(GameType.Archenemy) ? archenemyTeams : teams;
|
||||
|
||||
for (final int i : getParticipants()) {
|
||||
for (int i = 0; i < activePlayersNum; i++) {
|
||||
if (lastTeam == -1) {
|
||||
lastTeam = teamList.get(i);
|
||||
}
|
||||
@@ -977,7 +1092,7 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
|
||||
/** This listener unlocks the relevant buttons for players
|
||||
* and enables/disables archenemy combobox as appropriate. */
|
||||
private ItemListener iListenerVariants = new ItemListener() {
|
||||
/*private ItemListener iListenerVariants = new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent arg0) {
|
||||
FCheckBox cb = (FCheckBox) arg0.getSource();
|
||||
@@ -1043,7 +1158,7 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
|
||||
//This listener will look for a vanguard avatar being selected in the lists
|
||||
//and update the corresponding detail panel.
|
||||
/*private ListSelectionListener vgdLSListener = new ListSelectionListener() {
|
||||
private ListSelectionListener vgdLSListener = new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
int index = vgdAvatarLists.indexOf(e.getSource());
|
||||
@@ -1075,22 +1190,10 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
return appliedVariants.contains(GameType.Archenemy) ? archenemyTeams.get(playerIndex) : teams.get(playerIndex);
|
||||
}
|
||||
|
||||
/*public List<FList<Object>> getPlanarDeckLists() {
|
||||
return planarDeckLists;
|
||||
public boolean isPlayerAI(final int playernum) {
|
||||
return playerPanels.get(playernum).isPlayerAI();
|
||||
}
|
||||
|
||||
public List<FList<Object>> getCommanderDeckLists() {
|
||||
return commanderDeckLists;
|
||||
}
|
||||
|
||||
public List<FList<Object>> getSchemeDeckLists() {
|
||||
return schemeDeckLists;
|
||||
}
|
||||
|
||||
public List<FList<Object>> getVanguardLists() {
|
||||
return vgdAvatarLists;
|
||||
}*/
|
||||
|
||||
public boolean isPlayerArchenemy(final int playernum) {
|
||||
return playerPanels.get(playernum).playerIsArchenemy;
|
||||
}
|
||||
@@ -1142,18 +1245,4 @@ public class ConstructedScreen extends LaunchScreen {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** update vanguard list. */
|
||||
public void updateVanguardList(int playerIndex) {
|
||||
/*FList<Object> vgdList = getVanguardLists().get(playerIndex);
|
||||
Object lastSelection = vgdList.getSelectedValue();
|
||||
vgdList.setListData(isPlayerAI(playerIndex) ? aiListData : humanListData);
|
||||
if (null != lastSelection) {
|
||||
vgdList.setSelectedValue(lastSelection, true);
|
||||
}
|
||||
|
||||
if (-1 == vgdList.getSelectedIndex()) {
|
||||
vgdList.setSelectedIndex(0);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,17 @@ public class FComboBox<E> extends FTextField {
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
if (!items.isEmpty()) {
|
||||
setSelectedItem(items.get(0)); //select first item by default
|
||||
}
|
||||
}
|
||||
|
||||
public void addItem(E item) {
|
||||
items.add(item);
|
||||
if (items.size() == 1) {
|
||||
setSelectedItem(item); //select first item by default
|
||||
}
|
||||
}
|
||||
|
||||
public boolean removeItem(E item) {
|
||||
@@ -81,6 +90,7 @@ public class FComboBox<E> extends FTextField {
|
||||
selectedItem = item;
|
||||
super.setText(item.toString());
|
||||
}
|
||||
else { return; }
|
||||
}
|
||||
else {
|
||||
selectedItem = null;
|
||||
@@ -104,12 +114,6 @@ public class FComboBox<E> extends FTextField {
|
||||
setText(text0);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
if (!items.isEmpty()) {
|
||||
setSelectedItem(items.get(0)); //select first item by default
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tap(float x, float y, int count) {
|
||||
dropDown.setVisible(!dropDown.isVisible());
|
||||
|
||||
@@ -83,6 +83,13 @@ public class FList<E> extends FScrollPane {
|
||||
groups.clear();
|
||||
}
|
||||
|
||||
public void setListData(Iterable<E> items0) {
|
||||
clear();
|
||||
for (E item : items0) {
|
||||
addItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return groups.isEmpty();
|
||||
}
|
||||
@@ -95,7 +102,7 @@ public class FList<E> extends FScrollPane {
|
||||
return count;
|
||||
}
|
||||
|
||||
public Object getItemAt(int index) {
|
||||
public E getItemAt(int index) {
|
||||
int count = 0;
|
||||
for (ListGroup group : groups) {
|
||||
for (ListItem item : group.items) {
|
||||
@@ -108,6 +115,19 @@ public class FList<E> extends FScrollPane {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getIndexOf(E value) {
|
||||
int count = 0;
|
||||
for (ListGroup group : groups) {
|
||||
for (ListItem item : group.items) {
|
||||
if (item.value == value) {
|
||||
return count;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void setListItemRenderer(ListItemRenderer<E> renderer0) {
|
||||
renderer = renderer0;
|
||||
}
|
||||
|
||||
54
forge-m-base/src/forge/utils/XmlUtil.java
Normal file
54
forge-m-base/src/forge/utils/XmlUtil.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.utils;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.StringWriter;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public class XmlUtil {
|
||||
|
||||
/**
|
||||
* Node to string.
|
||||
*
|
||||
* @param node the node
|
||||
* @return the string
|
||||
*/
|
||||
public static String nodeToString(final Node node) {
|
||||
final StringWriter sw = new StringWriter();
|
||||
try {
|
||||
final Transformer t = TransformerFactory.newInstance().newTransformer();
|
||||
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
t.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
t.transform(new DOMSource(node), new StreamResult(sw));
|
||||
} catch (final TransformerException te) {
|
||||
System.out.println("nodeToString Transformer Exception");
|
||||
}
|
||||
return sw.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user