Refactor some quest code to make it reusable by mobile game

This commit is contained in:
drdev
2014-07-06 02:37:23 +00:00
parent acc648cf08
commit c89cc33cd6
35 changed files with 834 additions and 745 deletions

9
.gitattributes vendored
View File

@@ -871,13 +871,10 @@ forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDecks.java
forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestDraft.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuQuestPrefs.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/DialogChooseSets.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/IVQuestStats.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlDraftEvent.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/PnlEvent.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/QuestDraftUtils.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/QuestFileLister.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/QuestPreferencesHandler.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/SSubmenuQuestUtil.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuChallenges.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuDuels.java -text
forge-gui-desktop/src/main/java/forge/screens/home/quest/VSubmenuQuestData.java -text
@@ -1202,7 +1199,7 @@ forge-gui-mobile/src/forge/screens/match/winlose/GauntletWinLose.java -text
forge-gui-mobile/src/forge/screens/match/winlose/LimitedWinLose.java -text
forge-gui-mobile/src/forge/screens/match/winlose/ViewWinLose.java -text
forge-gui-mobile/src/forge/screens/quest/QuestDuelsScreen.java -text
forge-gui-mobile/src/forge/screens/quest/QuestScreen.java -text
forge-gui-mobile/src/forge/screens/quest/QuestMenu.java -text
forge-gui-mobile/src/forge/screens/sealed/SealedScreen.java -text
forge-gui-mobile/src/forge/screens/settings/FilesPage.java -text
forge-gui-mobile/src/forge/screens/settings/GuiDownloader.java -text
@@ -16454,6 +16451,8 @@ forge-gui/src/main/java/forge/events/UiEventBlockerAssigned.java -text
forge-gui/src/main/java/forge/gauntlet/GauntletData.java -text
forge-gui/src/main/java/forge/gauntlet/GauntletIO.java -text
forge-gui/src/main/java/forge/interfaces/IButton.java -text
forge-gui/src/main/java/forge/interfaces/ICheckBox.java -text
forge-gui/src/main/java/forge/interfaces/IComboBox.java -text
forge-gui/src/main/java/forge/interfaces/IGuiBase.java -text
forge-gui/src/main/java/forge/interfaces/IProgressBar.java -text
forge-gui/src/main/java/forge/interfaces/ITextField.java -text
@@ -16534,9 +16533,11 @@ forge-gui/src/main/java/forge/properties/SavePreferencesListener.java svneol=nat
forge-gui/src/main/java/forge/properties/package-info.java svneol=native#text/plain
forge-gui/src/main/java/forge/quest/BoosterUtils.java svneol=native#text/plain
forge-gui/src/main/java/forge/quest/IQuestRewardCard.java -text
forge-gui/src/main/java/forge/quest/IVQuestStats.java -text
forge-gui/src/main/java/forge/quest/QuestController.java -text
forge-gui/src/main/java/forge/quest/QuestDeckGroupMap.java -text
forge-gui/src/main/java/forge/quest/QuestDeckMap.java -text
forge-gui/src/main/java/forge/quest/QuestDraftUtils.java -text
forge-gui/src/main/java/forge/quest/QuestEvent.java -text
forge-gui/src/main/java/forge/quest/QuestEventChallenge.java svneol=native#text/plain
forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java -text

View File

@@ -33,6 +33,7 @@ import forge.events.UiEvent;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameType;
import forge.game.Match;
import forge.game.card.Card;
import forge.game.combat.Combat;
import forge.game.event.GameEventTurnBegan;
@@ -47,12 +48,16 @@ import forge.gui.FNetOverlay;
import forge.gui.GuiChoose;
import forge.gui.GuiUtils;
import forge.gui.SOverlayUtils;
import forge.gui.framework.FScreen;
import forge.gui.framework.SDisplayUtil;
import forge.gui.framework.SLayoutIO;
import forge.interfaces.IButton;
import forge.interfaces.IGuiBase;
import forge.item.PaperCard;
import forge.match.input.InputQueue;
import forge.model.FModel;
import forge.screens.deckeditor.CDeckEditorUI;
import forge.screens.deckeditor.controllers.CEditorQuestCardShop;
import forge.screens.match.CMatchUI;
import forge.screens.match.VMatchUI;
import forge.screens.match.ViewWinLose;
@@ -450,6 +455,11 @@ public class GuiDesktop implements IGuiBase {
return FControl.instance.getGuiPlayer();
}
@Override
public LobbyPlayer getAiPlayer(String name) {
return FControl.instance.getAiPlayer(name);
}
@Override
public LobbyPlayer createAiPlayer() {
return FControl.instance.getAiPlayer();
@@ -484,4 +494,40 @@ public class GuiDesktop implements IGuiBase {
public void clearImageCache() {
ImageCache.clear();
}
@Override
public void startGame(Match match) {
SOverlayUtils.startGameOverlay();
SOverlayUtils.showOverlay();
Singletons.getControl().startGameWithUi(match);
}
@Override
public void continueMatch(Match match) {
Singletons.getControl().endCurrentGame();
if (match == null) {
Singletons.getControl().setCurrentScreen(FScreen.HOME_SCREEN);
}
else {
Singletons.getControl().startGameWithUi(match);
}
}
@Override
public void showSpellShop() {
Singletons.getControl().setCurrentScreen(FScreen.QUEST_CARD_SHOP);
CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(
new CEditorQuestCardShop(FModel.getQuest()));
}
@Override
public void showBazaar() {
Singletons.getControl().setCurrentScreen(FScreen.QUEST_BAZAAR);
Singletons.getView().getFrame().validate();
}
@Override
public void setPlayerAvatar(LobbyPlayer player, String iconImageKey) {
CMatchUI.SINGLETON_INSTANCE.avatarImages.put(player, iconImageKey);
}
}

View File

@@ -7,6 +7,7 @@ import forge.gui.framework.ICDoc;
import forge.model.FModel;
import forge.quest.QuestController;
import forge.quest.QuestEventChallenge;
import forge.quest.QuestUtil;
import forge.quest.bazaar.QuestItemType;
import forge.quest.bazaar.QuestPetController;
import forge.screens.home.CHomeUI;
@@ -41,29 +42,29 @@ public enum CSubmenuChallenges implements ICDoc {
view.getBtnSpellShop().setCommand(
new UiCommand() { @Override
public void run() { SSubmenuQuestUtil.showSpellShop(); } });
public void run() { QuestUtil.showSpellShop(); } });
view.getBtnBazaar().setCommand(
new UiCommand() { @Override
public void run() { SSubmenuQuestUtil.showBazaar(); } });
public void run() { QuestUtil.showBazaar(); } });
view.getBtnUnlock().setCommand(
new UiCommand() { @Override
public void run() { SSubmenuQuestUtil.chooseAndUnlockEdition(); CSubmenuChallenges.this.update(); } });
public void run() { QuestUtil.chooseAndUnlockEdition(); CSubmenuChallenges.this.update(); } });
view.getBtnTravel().setCommand(
new UiCommand() { @Override
public void run() { SSubmenuQuestUtil.travelWorld(); CSubmenuChallenges.this.update(); } });
public void run() { QuestUtil.travelWorld(); CSubmenuChallenges.this.update(); } });
view.getBtnStart().addActionListener(
new ActionListener() { @Override
public void actionPerformed(final ActionEvent e) { SSubmenuQuestUtil.startGame(); } });
public void actionPerformed(final ActionEvent e) { QuestUtil.startGame(); } });
((FLabel) view.getLblZep()).setCommand(
new UiCommand() {
@Override
public void run() {
if (!SSubmenuQuestUtil.checkActiveQuest("Launch a Zeppelin.")) {
if (!QuestUtil.checkActiveQuest("Launch a Zeppelin.")) {
return;
}
FModel.getQuest().getAchievements().setCurrentChallenges(null);
@@ -124,7 +125,7 @@ public enum CSubmenuChallenges implements ICDoc {
*/
@Override
public void update() {
SSubmenuQuestUtil.updateQuestView(VSubmenuChallenges.SINGLETON_INSTANCE);
QuestUtil.updateQuestView(VSubmenuChallenges.SINGLETON_INSTANCE);
final VSubmenuChallenges view = VSubmenuChallenges.SINGLETON_INSTANCE;
final QuestController qCtrl = FModel.getQuest();

View File

@@ -6,6 +6,7 @@ import forge.gui.framework.ICDoc;
import forge.model.FModel;
import forge.quest.QuestController;
import forge.quest.QuestEventDuel;
import forge.quest.QuestUtil;
import forge.quest.bazaar.QuestPetController;
import forge.screens.home.CHomeUI;
import forge.toolbox.JXButtonPanel;
@@ -35,23 +36,23 @@ public enum CSubmenuDuels implements ICDoc {
view.getBtnSpellShop().setCommand(
new UiCommand() { @Override
public void run() { SSubmenuQuestUtil.showSpellShop(); } });
public void run() { QuestUtil.showSpellShop(); } });
view.getBtnBazaar().setCommand(
new UiCommand() { @Override
public void run() { SSubmenuQuestUtil.showBazaar(); } });
public void run() { QuestUtil.showBazaar(); } });
view.getBtnTravel().setCommand(
new UiCommand() { @Override
public void run() { SSubmenuQuestUtil.travelWorld(); CSubmenuDuels.this.update(); } });
public void run() { QuestUtil.travelWorld(); CSubmenuDuels.this.update(); } });
view.getBtnUnlock().setCommand(
new UiCommand() { @Override
public void run() { SSubmenuQuestUtil.chooseAndUnlockEdition(); CSubmenuDuels.this.update(); } });
public void run() { QuestUtil.chooseAndUnlockEdition(); CSubmenuDuels.this.update(); } });
view.getBtnStart().addActionListener(
new ActionListener() { @Override
public void actionPerformed(final ActionEvent e) { SSubmenuQuestUtil.startGame(); } });
public void actionPerformed(final ActionEvent e) { QuestUtil.startGame(); } });
final QuestController quest = FModel.getQuest();
view.getCbPlant().addActionListener(new ActionListener() {
@@ -85,11 +86,11 @@ public enum CSubmenuDuels implements ICDoc {
view.getBtnRandomOpponent().setCommand(new UiCommand() {
@Override
public void run() {
if (SSubmenuQuestUtil.canStartGame()) {
if (QuestUtil.canStartGame()) {
FModel.getQuest().getDuelsManager().randomizeOpponents();
final List<QuestEventDuel> duels = FModel.getQuest().getDuelsManager().generateDuels();
SSubmenuQuestUtil.setEvent(duels.get((int) (Math.random() * duels.size())));
SSubmenuQuestUtil.startGame();
QuestUtil.setEvent(duels.get((int) (Math.random() * duels.size())));
QuestUtil.startGame();
}
}
});
@@ -118,7 +119,7 @@ public enum CSubmenuDuels implements ICDoc {
*/
@Override
public void update() {
SSubmenuQuestUtil.updateQuestView(VSubmenuDuels.SINGLETON_INSTANCE);
QuestUtil.updateQuestView(VSubmenuDuels.SINGLETON_INSTANCE);
final VSubmenuDuels view = VSubmenuDuels.SINGLETON_INSTANCE;

View File

@@ -242,7 +242,7 @@ public enum CSubmenuQuestData implements ICDoc {
questName = FOptionPane.showInputDialog("Poets will remember your quest as:", "Quest Name");
if (questName == null) { return; }
questName = SSubmenuQuestUtil.cleanString(questName);
questName = QuestUtil.cleanString(questName);
if (questName.isEmpty()) {
FOptionPane.showMessageDialog("Please specify a quest name.");

View File

@@ -9,6 +9,7 @@ import forge.gui.framework.ICDoc;
import forge.itemmanager.ItemManagerConfig;
import forge.model.FModel;
import forge.quest.QuestController;
import forge.quest.QuestUtil;
import forge.quest.data.QuestPreferences.QPref;
import forge.screens.deckeditor.CDeckEditorUI;
import forge.screens.deckeditor.controllers.CEditorQuest;
@@ -55,7 +56,7 @@ public enum CSubmenuQuestDecks implements ICDoc {
VSubmenuQuestDecks.SINGLETON_INSTANCE.getBtnNewDeck().setCommand(new UiCommand() {
@Override
public void run() {
if (!SSubmenuQuestUtil.checkActiveQuest("Create a Deck.")) {
if (!QuestUtil.checkActiveQuest("Create a Deck.")) {
return;
}
Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_QUEST);

View File

@@ -37,7 +37,9 @@ import forge.limited.LimitedPoolType;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.quest.QuestController;
import forge.quest.QuestDraftUtils;
import forge.quest.QuestEventDraft;
import forge.quest.QuestUtil;
import forge.quest.data.QuestAchievements;
import forge.screens.deckeditor.CDeckEditorUI;
import forge.screens.deckeditor.controllers.CEditorQuestDraftingProcess;
@@ -531,7 +533,7 @@ public enum CSubmenuQuestDraft implements ICDoc {
return;
}
QuestEventDraft draftEvent = SSubmenuQuestUtil.getDraftEvent();
QuestEventDraft draftEvent = QuestUtil.getDraftEvent();
long creditsAvailable = FModel.getQuest().getAssets().getCredits();
if (creditsAvailable < draftEvent.getEntryFee()) {

View File

@@ -1,61 +0,0 @@
package forge.screens.home.quest;
import forge.toolbox.FCheckBox;
import forge.toolbox.FComboBoxWrapper;
import forge.toolbox.FLabel;
/** Dictates methods required for a panel with stats/pet display. */
public interface IVQuestStats {
/** @return {@link forge.toolbox.FLabel} */
FLabel getBtnRandomOpponent();
/** @return {@link forge.toolbox.FLabel} */
FLabel getBtnBazaar();
/** @return {@link forge.toolbox.FLabel} */
FLabel getBtnSpellShop();
/** @return {@link forge.toolbox.FLabel} */
FLabel getBtnUnlock();
/** @return {@link forge.toolbox.FLabel} */
FLabel getBtnTravel();
/** @return {@link forge.toolbox.FLabel} */
FLabel getLblCredits();
/** @return {@link forge.toolbox.FLabel} */
FLabel getLblLife();
/** @return {@link forge.toolbox.FLabel} */
FLabel getLblWorld();
/** @return {@link forge.toolbox.FLabel} */
FLabel getLblWins();
/** @return {@link forge.toolbox.FLabel} */
FLabel getLblLosses();
/** @return {@link forge.toolbox.FLabel} */
FLabel getLblNextChallengeInWins();
/** @return {@link forge.toolbox.FLabel} */
FLabel getLblCurrentDeck();
/** @return {@link forge.toolbox.FLabel} */
FLabel getLblWinStreak();
/** @return {@link javax.swing.FComboBoxWrapper} */
FComboBoxWrapper<String> getCbxPet();
/** @return {@link forge.toolbox.FCheckBox} */
FCheckBox getCbPlant();
/** @return {@link forge.toolbox.FCheckBox} */
FCheckBox getCbCharm();
/** @return {@link forge.toolbox.FLabel} */
FLabel getLblZep();
}

View File

@@ -12,6 +12,7 @@ import javax.swing.event.ChangeListener;
import net.miginfocom.swing.MigLayout;
import forge.model.FModel;
import forge.quest.QuestEventDraft;
import forge.quest.QuestUtil;
import forge.toolbox.FRadioButton;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinColor;
@@ -56,7 +57,7 @@ public class PnlDraftEvent extends JPanel {
@Override
public void stateChanged(ChangeEvent arg0) {
if (radButton.isSelected()) {
SSubmenuQuestUtil.setDraftEvent(event);
QuestUtil.setDraftEvent(event);
}
}
});

View File

@@ -2,6 +2,7 @@ package forge.screens.home.quest;
import forge.ImageCache;
import forge.quest.QuestEvent;
import forge.quest.QuestUtil;
import forge.toolbox.FRadioButton;
import forge.toolbox.FSkin;
import forge.toolbox.FTextArea;
@@ -60,7 +61,7 @@ class PnlEvent extends JPanel {
@Override
public void stateChanged(ChangeEvent arg0) {
if (rad.isSelected()) {
SSubmenuQuestUtil.setEvent(event);
QuestUtil.setEvent(event);
}
}
});

View File

@@ -3,6 +3,7 @@ package forge.screens.home.quest;
import forge.UiCommand;
import forge.assets.FSkinProp;
import forge.properties.ForgeConstants;
import forge.quest.QuestUtil;
import forge.quest.data.QuestData;
import forge.toolbox.FLabel;
import forge.toolbox.FMouseAdapter;
@@ -307,7 +308,7 @@ public class QuestFileLister extends JPanel {
questName = FOptionPane.showInputDialog("Rename quest to:", "Quest Rename", null, oldQuestName);
if (questName == null) { return; }
questName = SSubmenuQuestUtil.cleanString(questName);
questName = QuestUtil.cleanString(questName);
if (questName.equals(oldQuestName)) { return; } //quit if chose same name
if (questName.isEmpty()) {

View File

@@ -1,544 +0,0 @@
package forge.screens.home.quest;
import forge.FThreads;
import forge.GuiBase;
import forge.LobbyPlayer;
import forge.Singletons;
import forge.card.CardEdition;
import forge.control.FControl;
import forge.deck.Deck;
import forge.game.GameRules;
import forge.game.GameType;
import forge.game.Match;
import forge.game.player.RegisteredPlayer;
import forge.gui.GuiChoose;
import forge.gui.SOverlayUtils;
import forge.gui.framework.FScreen;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.quest.*;
import forge.quest.bazaar.QuestItemType;
import forge.quest.bazaar.QuestPetController;
import forge.quest.data.QuestAchievements;
import forge.quest.data.QuestAssets;
import forge.quest.data.QuestPreferences.QPref;
import forge.screens.deckeditor.CDeckEditorUI;
import forge.screens.deckeditor.controllers.CEditorQuestCardShop;
import forge.screens.match.CMatchUI;
import forge.toolbox.FOptionPane;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedLabel;
import org.apache.commons.lang3.tuple.ImmutablePair;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* Utilities for the quest submenu, all over the MVC spectrum.
* If a piece of code can be reused, it's dumped here.
*
* <br><br><i>(S at beginning of class name denotes a static factory.)</i>
*/
public class SSubmenuQuestUtil {
private static QuestEvent event;
private static QuestEventDraft draftEvent;
/**
* <p>
* nextChallengeInWins.
* </p>
*
* @return a int.
*/
public static int nextChallengeInWins() {
final QuestController qData = FModel.getQuest();
final int challengesPlayed = qData.getAchievements().getChallengesPlayed();
final int wins = qData.getAchievements().getWin();
final int turnsToUnlock = FModel.getQuest().getTurnsToUnlockChallenge();
final int delta;
// First challenge unlocks after minimum wins reached.
if (wins < 2 * turnsToUnlock) {
delta = 2 * turnsToUnlock - wins;
}
else {
// More than enough wins
if (wins / turnsToUnlock > challengesPlayed) {
delta = 0;
}
// This part takes the "unlimited challenge" bug into account;
// a player could have an inflated challengesPlayed value.
// Added 09-2012, can be removed after a while.
else if (wins < challengesPlayed * turnsToUnlock) {
delta = (challengesPlayed * turnsToUnlock - wins) + turnsToUnlock;
}
// Data OK, but not enough wins yet (default).
else {
delta = turnsToUnlock - wins % turnsToUnlock;
}
}
return (delta > 0) ? delta : 0;
}
private static void updatePlantAndPetForView(final IVQuestStats view, final QuestController qCtrl) {
for (int iSlot = 0; iSlot < QuestController.MAX_PET_SLOTS; iSlot++) {
final List<QuestPetController> petList = qCtrl.getPetsStorage().getAvaliablePets(iSlot, qCtrl.getAssets());
final String currentPetName = qCtrl.getSelectedPet(iSlot);
if (iSlot == 0) { // Plant visiblity
if (petList.isEmpty()) {
view.getCbPlant().setVisible(false);
}
else {
view.getCbPlant().setVisible(true);
view.getCbPlant().setSelected(currentPetName != null);
}
}
if (iSlot == 1) {
view.getCbxPet().removeAllItems();
// Pet list visibility
if (petList.size() > 0) {
view.getCbxPet().setVisible(true);
view.getCbxPet().addItem("Don't summon a pet");
for (final QuestPetController pet : petList) {
String name = "Summon " + pet.getName();
view.getCbxPet().addItem(name);
if (pet.getName().equals(currentPetName)) {
view.getCbxPet().setSelectedItem(name);
}
}
} else {
view.getCbxPet().setVisible(false);
}
}
}
if(qCtrl.getAssets().hasItem(QuestItemType.CHARM)) {
view.getCbCharm().setVisible(true);
} else {
view.getCbCharm().setVisible(false);
}
if (view.equals(VSubmenuChallenges.SINGLETON_INSTANCE)) {
view.getLblZep().setVisible(qCtrl.getAssets().hasItem(QuestItemType.ZEPPELIN));
if (qCtrl.getAssets().getItemLevel(QuestItemType.ZEPPELIN) == 2) {
view.getLblZep().setEnabled(false);
view.getLblZep().setForeground(Color.gray);
}
else {
view.getLblZep().setEnabled(true);
view.getLblZep().setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
}
}
else {
view.getLblZep().setVisible(false);
}
}
/**
* Updates all quest info in a view, using
* retrieval methods dictated in IVQuestStats.<br>
* - Stats<br>
* - Pets<br>
* - Current deck info<br>
* - "Challenge In" info<br>
*
* @param view0 {@link forge.screens.home.quest.IVQuestStats}
*/
public static void updateQuestView(final IVQuestStats view0) {
final QuestController qCtrl = FModel.getQuest();
final QuestAchievements qA = qCtrl.getAchievements();
final QuestAssets qS = qCtrl.getAssets();
if (qA == null) { return; }
// Fantasy UI display
view0.getLblNextChallengeInWins().setVisible(true);
view0.getBtnBazaar().setVisible(true);
view0.getLblLife().setVisible(true);
// Stats panel
view0.getLblCredits().setText("Credits: " + qS.getCredits());
view0.getLblLife().setText("Life: " + qS.getLife(qCtrl.getMode()));
view0.getLblWins().setText("Wins: " + qA.getWin());
view0.getLblLosses().setText("Losses: " + qA.getLost());
view0.getLblWorld().setText("World: " + (qCtrl.getWorld() == null ? "(none)" : qCtrl.getWorld()));
// Show or hide the set unlocking button
view0.getBtnUnlock().setVisible(qCtrl.getUnlocksTokens() > 0 && qCtrl.getWorldFormat() == null);
// Challenge in wins
final int num = SSubmenuQuestUtil.nextChallengeInWins();
final String str;
if (num == 0) {
str = "Your exploits have been noticed. An opponent has challenged you.";
}
else if (num == 1) {
str = "A new challenge will be available after 1 more win.";
}
else {
str = "A new challenge will be available in " + num + " wins.";
}
view0.getLblNextChallengeInWins().setText(str);
view0.getLblWinStreak().setText(
"<html>Win streak: " + qA.getWinStreakCurrent()
+ "<br>&nbsp; (Best: " + qA.getWinStreakBest() + ")</html>");
// Current deck message
final SkinnedLabel lblCurrentDeck = view0.getLblCurrentDeck();
if (SSubmenuQuestUtil.getCurrentDeck() == null) {
lblCurrentDeck.setForeground(Color.red.darker());
lblCurrentDeck.setText("Build, then select a deck in the \"Quest Decks\" submenu.");
}
else {
lblCurrentDeck.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
lblCurrentDeck.setText("Your current deck is \""
+ SSubmenuQuestUtil.getCurrentDeck().getName() + "\".");
}
// Start panel: pet, plant, zep.
if (qCtrl.getMode() == QuestMode.Fantasy) {
updatePlantAndPetForView(view0, qCtrl);
}
else {
// Classic mode display changes
view0.getCbxPet().setVisible(false);
view0.getCbPlant().setVisible(false);
view0.getCbCharm().setVisible(false);
view0.getLblZep().setVisible(false);
view0.getLblNextChallengeInWins().setVisible(false);
view0.getBtnBazaar().setVisible(false);
view0.getLblLife().setVisible(false);
}
}
/** @return {@link forge.deck.Deck} */
public static Deck getCurrentDeck() {
Deck d = null;
if (FModel.getQuest().getAssets() != null) {
d = FModel.getQuest().getMyDecks().get(
FModel.getQuestPreferences().getPref(QPref.CURRENT_DECK));
}
return d;
}
/** Updates the current selected quest event, used when game is started.
* @param event0 {@link forge.quest.QuestEvent}
*/
public static void setEvent(final QuestEvent event0) {
SSubmenuQuestUtil.event = event0;
}
public static void setDraftEvent(final QuestEventDraft event0) {
SSubmenuQuestUtil.draftEvent = event0;
}
public static QuestEventDraft getDraftEvent() {
return draftEvent;
}
public static boolean checkActiveQuest(String location) {
QuestController qc = FModel.getQuest();
if (qc == null || qc.getAssets() == null) {
String msg = "Please create a Quest before attempting to " + location;
FOptionPane.showErrorDialog(msg, "No Quest");
System.out.println(msg);
return false;
}
return true;
}
/** */
public static void showSpellShop() {
if (!checkActiveQuest("Visit the Spell Shop.")) {
return;
}
Singletons.getControl().setCurrentScreen(FScreen.QUEST_CARD_SHOP);
CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(
new CEditorQuestCardShop(FModel.getQuest()));
}
/** */
public static void showBazaar() {
if (!checkActiveQuest("Visit the Bazaar.")) {
return;
}
Singletons.getControl().setCurrentScreen(FScreen.QUEST_BAZAAR);
Singletons.getView().getFrame().validate();
}
/** */
public static void chooseAndUnlockEdition() {
if (!checkActiveQuest("Unlock Editions.")) {
return;
}
final QuestController qData = FModel.getQuest();
ImmutablePair<CardEdition, Integer> toUnlock = QuestUtilUnlockSets.chooseSetToUnlock(qData, false, null);
if (toUnlock == null) {
return;
}
CardEdition unlocked = toUnlock.left;
qData.getAssets().subtractCredits(toUnlock.right);
FOptionPane.showMessageDialog("You have successfully unlocked " + unlocked.getName() + "!",
unlocked.getName() + " unlocked!", null);
QuestUtilUnlockSets.doUnlock(qData, unlocked);
}
/** */
public static void travelWorld() {
if (!checkActiveQuest("Travel between worlds.")) {
return;
}
List<QuestWorld> worlds = new ArrayList<QuestWorld>();
final QuestController qCtrl = FModel.getQuest();
for (QuestWorld qw : FModel.getWorlds()) {
if (qCtrl.getWorld() != qw) {
worlds.add(qw);
}
}
if (worlds.size() < 1) {
FOptionPane.showErrorDialog("There are currently no worlds you can travel to\nin this version of Forge.", "No Worlds");
return;
}
final String setPrompt = "Where do you wish to travel?";
final QuestWorld newWorld = GuiChoose.oneOrNone(setPrompt, worlds);
if (worlds.indexOf(newWorld) < 0) {
return;
}
if (qCtrl.getWorld() != newWorld) {
boolean needRemove = false;
if (nextChallengeInWins() < 1 && qCtrl.getAchievements().getCurrentChallenges().size() > 0) {
needRemove = true;
if (!FOptionPane.showConfirmDialog(
"You have uncompleted challenges in your current world. If you travel now, they will be LOST!"
+ "\nAre you sure you wish to travel anyway?\n"
+ "(Click \"No\" to go back and complete your current challenges first.)",
"WARNING: Uncompleted challenges")) {
return;
}
}
if (needRemove) {
// Remove current challenges.
while (nextChallengeInWins() == 0) {
qCtrl.getAchievements().addChallengesPlayed();
}
qCtrl.getAchievements().getCurrentChallenges().clear();
}
qCtrl.setWorld(newWorld);
qCtrl.resetDuelsManager();
qCtrl.resetChallengesManager();
// Note that the following can be (ab)used to re-randomize your opponents by travelling to a different
// world and back. To prevent this, simply delete the following line that randomizes DuelsManager.
// (OTOH, you can 'swap' opponents even more easily by simply selecting a different quest data file and
// then re-selecting your current quest data file.)
qCtrl.getDuelsManager().randomizeOpponents();
qCtrl.getCards().clearShopList();
qCtrl.save();
}
}
/** */
public static void startGame() {
if (!checkActiveQuest("Start a duel.") || null == event) {
return;
}
final QuestController qData = FModel.getQuest();
Deck deck = null;
if (event instanceof QuestEventChallenge) {
// Predefined HumanDeck
deck = ((QuestEventChallenge) event).getHumanDeck();
}
if (deck == null) {
// If no predefined Deck, use the Player's Deck
deck = SSubmenuQuestUtil.getCurrentDeck();
}
if (deck == null) {
String msg = "Please select a Quest Deck.";
FOptionPane.showErrorDialog(msg, "No Deck");
System.out.println(msg);
return;
}
if (FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) {
String errorMessage = GameType.Quest.getDecksFormat().getDeckConformanceProblem(deck);
if (null != errorMessage) {
FOptionPane.showErrorDialog("Your deck " + errorMessage + " Please edit or choose a different deck.", "Invalid Deck");
return;
}
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
SOverlayUtils.startGameOverlay();
SOverlayUtils.showOverlay();
}
});
final SwingWorker<Object, Void> worker = new SwingWorker<Object, Void>() {
@Override
public Object doInBackground() {
qData.getDuelsManager().randomizeOpponents();
qData.setCurrentEvent(event);
qData.save();
return null;
}
@Override
public void done() {
SOverlayUtils.hideOverlay();
}
};
worker.execute();
int extraLifeHuman = 0;
Integer lifeHuman = null;
boolean useBazaar = true;
Boolean forceAnte = null;
int lifeAI = 20;
if (event instanceof QuestEventChallenge) {
QuestEventChallenge qc = ((QuestEventChallenge) event);
lifeAI = qc.getAILife();
lifeHuman = qc.getHumanLife();
if (qData.getAssets().hasItem(QuestItemType.ZEPPELIN)) {
extraLifeHuman = 3;
}
useBazaar = qc.isUseBazaar();
forceAnte = qc.isForceAnte();
}
RegisteredPlayer humanStart = new RegisteredPlayer(deck);
RegisteredPlayer aiStart = new RegisteredPlayer(event.getEventDeck());
if (lifeHuman != null) {
humanStart.setStartingLife(lifeHuman);
} else {
humanStart.setStartingLife(qData.getAssets().getLife(qData.getMode()) + extraLifeHuman);
}
if (useBazaar) {
humanStart.setCardsOnBattlefield(QuestUtil.getHumanStartingCards(qData, event));
aiStart.setStartingLife(lifeAI);
aiStart.setCardsOnBattlefield(QuestUtil.getComputerStartingCards(event));
}
List<RegisteredPlayer> starter = new ArrayList<RegisteredPlayer>();
starter.add(humanStart.setPlayer(GuiBase.getInterface().getQuestPlayer()));
LobbyPlayer aiPlayer = FControl.instance.getAiPlayer(event.getOpponent() == null ? event.getTitle() : event.getOpponent());
CMatchUI.SINGLETON_INSTANCE.avatarImages.put(aiPlayer, event.getIconImageKey());
starter.add(aiStart.setPlayer(aiPlayer));
boolean useRandomFoil = FModel.getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL);
for(RegisteredPlayer rp : starter) {
rp.setRandomFoil(useRandomFoil);
}
boolean useAnte = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE);
boolean matchAnteRarity = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE_MATCH_RARITY);
if(forceAnte != null)
useAnte = forceAnte.booleanValue();
GameRules rules = new GameRules(GameType.Quest);
rules.setPlayForAnte(useAnte);
rules.setMatchAnteRarity(matchAnteRarity);
rules.setGamesPerMatch(qData.getCharmState() ? 5 : 3);
rules.setManaBurn(FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN));
rules.canCloneUseTargetsImage = FModel.getPreferences().getPrefBoolean(FPref.UI_CLONE_MODE_SOURCE);
final Match mc = new Match(rules, starter);
FThreads.invokeInEdtLater(new Runnable(){
@Override
public void run() {
Singletons.getControl().startGameWithUi(mc);
// no overlays here?
}
});
}
/**
* Checks to see if a game can be started and displays relevant dialogues.
* @return
*/
public static boolean canStartGame() {
if (!checkActiveQuest("Start a duel.") || null == event) {
return false;
}
Deck deck = null;
if (event instanceof QuestEventChallenge) {
// Predefined HumanDeck
deck = ((QuestEventChallenge) event).getHumanDeck();
}
if (deck == null) {
// If no predefined Deck, use the Player's Deck
deck = SSubmenuQuestUtil.getCurrentDeck();
}
if (deck == null) {
String msg = "Please select a Quest Deck.";
FOptionPane.showErrorDialog(msg, "No Deck");
System.out.println(msg);
return false;
}
if (FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) {
String errorMessage = GameType.Quest.getDecksFormat().getDeckConformanceProblem(deck);
if (null != errorMessage) {
FOptionPane.showErrorDialog("Your deck " + errorMessage + " Please edit or choose a different deck.", "Invalid Deck");
return false;
}
}
return true;
}
/** Duplicate in DeckEditorQuestMenu and
* probably elsewhere...can streamline at some point
* (probably shouldn't be here).
*
* @param in &emsp; {@link java.lang.String}
* @return {@link java.lang.String}
*/
public static String cleanString(final String in) {
final StringBuffer out = new StringBuffer();
final char[] c = in.toCharArray();
for (int i = 0; (i < c.length) && (i < 20); i++) {
if (Character.isLetterOrDigit(c[i]) || (c[i] == '-') || (c[i] == '_') || (c[i] == ' ')) {
out.append(c[i]);
}
}
return out.toString();
}
}

View File

@@ -4,6 +4,7 @@ import forge.assets.FSkinProp;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID;
import forge.quest.IVQuestStats;
import forge.screens.home.*;
import forge.toolbox.*;
import net.miginfocom.swing.MigLayout;
@@ -290,5 +291,9 @@ public enum VSubmenuChallenges implements IVSubmenu<CSubmenuChallenges>, IVQuest
public FLabel getBtnRandomOpponent() {
return null;
}
@Override
public boolean isChallengesView() {
return true;
}
}

View File

@@ -4,6 +4,8 @@ import forge.assets.FSkinProp;
import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID;
import forge.interfaces.IButton;
import forge.quest.IVQuestStats;
import forge.screens.home.*;
import forge.toolbox.*;
import net.miginfocom.swing.MigLayout;
@@ -178,7 +180,7 @@ public enum VSubmenuDuels implements IVSubmenu<CSubmenuDuels>, IVQuestStats {
}
@Override
public FLabel getLblLosses() {
public IButton getLblLosses() {
return lblLosses;
}
@@ -290,4 +292,9 @@ public enum VSubmenuDuels implements IVSubmenu<CSubmenuDuels>, IVQuestStats {
public FCheckBox getCbCharm() {
return cbCharm;
}
@Override
public boolean isChallengesView() {
return false;
}
}

View File

@@ -42,7 +42,7 @@ import forge.item.InventoryItem;
import forge.menus.IMenuProvider;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.screens.home.quest.QuestDraftUtils;
import forge.quest.QuestDraftUtils;
import forge.screens.match.controllers.*;
import forge.screens.match.menus.CMatchUIMenus;
import forge.screens.match.views.*;

View File

@@ -30,10 +30,10 @@ import forge.gui.SOverlayUtils;
import forge.gui.framework.FScreen;
import forge.model.FModel;
import forge.quest.QuestController;
import forge.quest.QuestDraftUtils;
import forge.screens.home.quest.CSubmenuChallenges;
import forge.screens.home.quest.CSubmenuDuels;
import forge.screens.home.quest.CSubmenuQuestDraft;
import forge.screens.home.quest.QuestDraftUtils;
import forge.screens.home.quest.VSubmenuQuestDraft;
import forge.toolbox.FOptionPane;
import forge.toolbox.FSkin;

View File

@@ -21,6 +21,7 @@ import forge.UiCommand;
import forge.assets.FSkinProp;
import forge.gui.framework.ILocalRepaint;
import forge.interfaces.IButton;
import forge.toolbox.FSkin.Colors;
import forge.toolbox.FSkin.SkinImage;
import forge.toolbox.FSkin.SkinnedButton;
@@ -248,4 +249,14 @@ public class FButton extends SkinnedButton implements ILocalRepaint, IButton {
}
});
}
@Override
public void setTextColor(FSkinProp color) {
setForeground(FSkin.getColor(Colors.fromSkinProp(color)));
}
@Override
public void setTextColor(int r, int g, int b) {
setForeground(new Color(r, g, b));
}
}

View File

@@ -1,12 +1,13 @@
package forge.toolbox;
import forge.interfaces.ICheckBox;
import forge.toolbox.FSkin.SkinnedCheckBox;
/**
* A custom instance of JCheckBox using Forge skin properties.
*/
@SuppressWarnings("serial")
public class FCheckBox extends SkinnedCheckBox {
public class FCheckBox extends SkinnedCheckBox implements ICheckBox {
public FCheckBox() {
this("");
}

View File

@@ -1,5 +1,6 @@
package forge.toolbox;
import forge.interfaces.IComboBox;
import forge.toolbox.FSkin.SkinFont;
import forge.toolbox.FSkin.SkinnedComboBox;
@@ -13,7 +14,7 @@ import java.awt.*;
import java.util.Vector;
@SuppressWarnings("serial")
public class FComboBox<E> extends SkinnedComboBox<E> {
public class FComboBox<E> extends SkinnedComboBox<E> implements IComboBox<E> {
public enum TextAlignment {
LEFT (SwingConstants.LEFT),
RIGHT (SwingConstants.RIGHT),

View File

@@ -1,5 +1,6 @@
package forge.toolbox;
import forge.interfaces.IComboBox;
import forge.toolbox.FComboBox.TextAlignment;
import forge.toolbox.FSkin.SkinFont;
@@ -16,7 +17,7 @@ import java.util.Vector;
* Wrapper for combo box with extra logic (either FComboBoxWrapper or FComboBoxPanel should be used instead of FComboBox so skinning works)
*
*/
public class FComboBoxWrapper<E> {
public class FComboBoxWrapper<E> implements IComboBox<E> {
private static final ArrayList<FComboBoxWrapper<?>> allWrappers = new ArrayList<FComboBoxWrapper<?>>();
@@ -123,10 +124,22 @@ public class FComboBoxWrapper<E> {
this.comboBox.setSkinFont(skinFont);
}
@Override
public boolean isVisible() {
return this.comboBox.isVisible();
}
@Override
public void setVisible(boolean aFlag) {
this.comboBox.setVisible(aFlag);
}
@Override
public boolean isEnabled() {
return this.comboBox.isEnabled();
}
@Override
public void setEnabled(boolean aFlag) {
this.comboBox.setEnabled(aFlag);
}

View File

@@ -1,8 +1,10 @@
package forge.toolbox;
import forge.UiCommand;
import forge.assets.FSkinProp;
import forge.gui.framework.ILocalRepaint;
import forge.interfaces.IButton;
import forge.toolbox.FSkin.Colors;
import forge.toolbox.FSkin.SkinColor;
import forge.toolbox.FSkin.SkinImage;
import forge.toolbox.FSkin.SkinnedLabel;
@@ -632,4 +634,14 @@ public class FLabel extends SkinnedLabel implements ILocalRepaint, IButton {
public void setCommand(UiCommand command0) {
cmdClick = command0;
}
@Override
public void setTextColor(FSkinProp color) {
setForeground(FSkin.getColor(Colors.fromSkinProp(color)));
}
@Override
public void setTextColor(int r, int g, int b) {
setForeground(new Color(r, g, b));
}
}

View File

@@ -363,6 +363,15 @@ public class FSkin {
skinProp = skinProp0;
}
public static Colors fromSkinProp(FSkinProp skinProp) {
for (final Colors c : Colors.values()) {
if (c.skinProp == skinProp) {
return c;
}
}
return null;
}
public static void updateAll() {
for (final Colors c : Colors.values()) {
c.updateColor();

View File

@@ -25,6 +25,7 @@ import forge.events.UiEvent;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameType;
import forge.game.Match;
import forge.game.card.Card;
import forge.game.combat.Combat;
import forge.game.event.GameEventTurnBegan;
@@ -369,6 +370,11 @@ public class GuiMobile implements IGuiBase {
return FControl.getGuiPlayer();
}
@Override
public LobbyPlayer getAiPlayer(String name) {
return FControl.getAiPlayer(name);
}
@Override
public LobbyPlayer createAiPlayer() {
return FControl.getAiPlayer();
@@ -403,4 +409,35 @@ public class GuiMobile implements IGuiBase {
public void clearImageCache() {
ImageCache.clear();
}
@Override
public void startGame(Match match) {
FControl.startGame(match);
}
@Override
public void continueMatch(Match match) {
FControl.endCurrentGame();
if (match == null) {
Forge.back();
}
else {
FControl.startGame(match);
}
}
@Override
public void showSpellShop() {
}
@Override
public void showBazaar() {
}
@Override
public void setPlayerAvatar(LobbyPlayer player, String iconImageKey) {
//Not needed for mobile game
}
}

View File

@@ -7,6 +7,7 @@ import java.util.Set;
import com.badlogic.gdx.Input.Keys;
import forge.menu.FPopupMenu;
import forge.screens.FScreen;
import forge.screens.match.FControl;
import forge.Graphics;
@@ -21,12 +22,14 @@ public abstract class LaunchScreen extends FScreen {
private static final float IMAGE_WIDTH = FSkinImage.BTN_START_UP.getWidth() * IMAGE_HEIGHT / FSkinImage.BTN_START_UP.getHeight();
private static final float PADDING = IMAGE_HEIGHT * 0.025f;
protected final StartButton btnStart;
protected final StartButton btnStart = add(new StartButton());
private boolean creatingMatch;
public LaunchScreen(String headerCaption) {
super(headerCaption);
btnStart = add(new StartButton());
}
public LaunchScreen(String headerCaption, FPopupMenu menu) {
super(headerCaption, menu);
}
@Override

View File

@@ -1,13 +1,21 @@
package forge.screens.quest;
public class QuestDuelsScreen extends QuestScreen {
import forge.screens.LaunchScreen;
public class QuestDuelsScreen extends LaunchScreen {
public QuestDuelsScreen() {
super("Quest Duels");
super("Quest Duels", new QuestMenu());
}
@Override
protected void doLayout(float startY, float width, float height) {
protected void doLayoutAboveBtnStart(float startY, float width, float height) {
// TODO Auto-generated method stub
}
@Override
protected boolean buildLaunchParams(LaunchParams launchParams) {
// TODO Auto-generated method stub
return false;
}
}

View File

@@ -0,0 +1,68 @@
package forge.screens.quest;
import forge.assets.FSkinImage;
import forge.menu.FMenuItem;
import forge.menu.FPopupMenu;
import forge.toolbox.FEvent;
import forge.toolbox.FEvent.FEventHandler;
public class QuestMenu extends FPopupMenu {
@Override
protected void buildMenu() {
addItem(new FMenuItem("Duels", FSkinImage.QUEST_GEAR, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Challenges", FSkinImage.QUEST_HEART, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Tournaments", FSkinImage.PACK, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Travel", FSkinImage.QUEST_MAP, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Spell Shop", FSkinImage.QUEST_BOOK, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Bazaar", FSkinImage.QUEST_BOTTLES, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Statistics", FSkinImage.MULTI, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Change Deck", FSkinImage.DECKLIST, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("New Quest", FSkinImage.NEW, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Load Quest", FSkinImage.OPEN, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Preferences", FSkinImage.SETTINGS, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
}
}

View File

@@ -1,68 +0,0 @@
package forge.screens.quest;
import forge.assets.FSkinImage;
import forge.menu.FMenuItem;
import forge.menu.FPopupMenu;
import forge.screens.FScreen;
import forge.toolbox.FEvent;
import forge.toolbox.FEvent.FEventHandler;
public abstract class QuestScreen extends FScreen {
protected QuestScreen(String headerCaption) {
super(headerCaption, new FPopupMenu() {
@Override
protected void buildMenu() {
addItem(new FMenuItem("Duels", FSkinImage.QUEST_GEAR, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Challenges", FSkinImage.QUEST_HEART, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Tournaments", FSkinImage.PACK, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Travel", FSkinImage.QUEST_MAP, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Spell Shop", FSkinImage.QUEST_BOOK, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Bazaar", FSkinImage.QUEST_BOTTLES, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Change Deck", FSkinImage.DECKLIST, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("New Quest", FSkinImage.NEW, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Load Quest", FSkinImage.OPEN, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
addItem(new FMenuItem("Preferences", FSkinImage.SETTINGS, new FEventHandler() {
@Override
public void handleEvent(FEvent e) {
}
}));
}
});
}
}

View File

@@ -6,9 +6,10 @@ import forge.Graphics;
import forge.assets.FImage;
import forge.assets.FSkinColor;
import forge.assets.FSkinColor.Colors;
import forge.interfaces.ICheckBox;
import forge.util.Utils;
public class FCheckBox extends FLabel {
public class FCheckBox extends FLabel implements ICheckBox {
private static final FSkinColor CHECK_COLOR = FSkinColor.get(Colors.CLR_TEXT);
private static final FSkinColor BOX_COLOR = CHECK_COLOR.alphaColor(0.5f);

View File

@@ -1,6 +1,7 @@
package forge.interfaces;
import forge.UiCommand;
import forge.assets.FSkinProp;
public interface IButton {
boolean isEnabled();
@@ -13,4 +14,6 @@ public interface IButton {
void setSelected(boolean b0);
boolean requestFocusInWindow();
void setCommand(UiCommand command0);
void setTextColor(FSkinProp color);
void setTextColor(int r, int g, int b);
}

View File

@@ -0,0 +1,10 @@
package forge.interfaces;
public interface ICheckBox {
boolean isEnabled();
void setEnabled(boolean b0);
boolean isVisible();
void setVisible(boolean b0);
boolean isSelected();
void setSelected(boolean b0);
}

View File

@@ -0,0 +1,11 @@
package forge.interfaces;
public interface IComboBox<E> {
boolean isEnabled();
void setEnabled(boolean b0);
boolean isVisible();
void setVisible(boolean b0);
void setSelectedItem(E item);
void addItem(E item);
void removeAllItems();
}

View File

@@ -17,6 +17,7 @@ import forge.events.UiEvent;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameType;
import forge.game.Match;
import forge.game.card.Card;
import forge.game.combat.Combat;
import forge.game.event.GameEventTurnBegan;
@@ -86,6 +87,7 @@ public interface IGuiBase {
void copyToClipboard(String text);
void browseToUrl(String url) throws Exception;
LobbyPlayer getGuiPlayer();
LobbyPlayer getAiPlayer(String name);
LobbyPlayer createAiPlayer();
LobbyPlayer createAiPlayer(String name, int avatarIndex);
LobbyPlayer getQuestPlayer();
@@ -93,4 +95,9 @@ public interface IGuiBase {
IAudioMusic createAudioMusic(String filename);
void startAltSoundSystem(String filename, boolean isSynchronized);
void clearImageCache();
void startGame(Match match);
void continueMatch(Match match);
void showSpellShop();
void showBazaar();
void setPlayerAvatar(LobbyPlayer player, String iconImageKey);
}

View File

@@ -0,0 +1,32 @@
package forge.quest;
import forge.interfaces.IButton;
import forge.interfaces.ICheckBox;
import forge.interfaces.IComboBox;
/** Dictates methods required for a panel with stats/pet display. */
public interface IVQuestStats {
IButton getBtnRandomOpponent();
IButton getBtnBazaar();
IButton getBtnSpellShop();
IButton getBtnUnlock();
IButton getBtnTravel();
IButton getLblCredits();
IButton getLblLife();
IButton getLblWorld();
IButton getLblWins();
IButton getLblLosses();
IButton getLblNextChallengeInWins();
IButton getLblCurrentDeck();
IButton getLblWinStreak();
IComboBox<String> getCbxPet();
ICheckBox getCbPlant();
ICheckBox getCbCharm();
IButton getLblZep();
boolean isChallengesView();
}

View File

@@ -1,47 +1,32 @@
package forge.screens.home.quest;
package forge.quest;
import java.util.ArrayList;
import java.util.List;
import javax.swing.SwingUtilities;
import forge.FThreads;
import forge.GuiBase;
import forge.Singletons;
import forge.deck.DeckGroup;
import forge.game.Game;
import forge.game.GameRules;
import forge.game.GameType;
import forge.game.Match;
import forge.game.player.RegisteredPlayer;
import forge.gui.SOverlayUtils;
import forge.gui.framework.FScreen;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.quest.QuestEventDraft;
public class QuestDraftUtils {
private static List<DraftMatchup> matchups = new ArrayList<DraftMatchup>();
public static boolean matchInProgress = false;
public static boolean aiMatchInProgress = false;
private static boolean waitForUserInput = false;
public static void continueMatch(Game lastGame) {
if (lastGame.getMatch().isMatchOver()) {
matchInProgress = false;
}
if (!matchInProgress) {
Singletons.getControl().endCurrentGame();
Singletons.getControl().setCurrentScreen(FScreen.HOME_SCREEN);
} else {
Singletons.getControl().endCurrentGame();
Singletons.getControl().startGameWithUi(lastGame.getMatch());
}
GuiBase.getInterface().continueMatch(matchInProgress ? lastGame.getMatch() : null);
}
public static void startNextMatch() {
@@ -151,11 +136,9 @@ public class QuestDraftUtils {
}
matchups.add(matchup);
}
public static void update() {
if (matchups.isEmpty()) {
if (!matchInProgress) {
aiMatchInProgress = false;
@@ -177,19 +160,12 @@ public class QuestDraftUtils {
matchInProgress = true;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
SOverlayUtils.startGameOverlay();
SOverlayUtils.showOverlay();
}
});
if (!nextMatch.hasHumanPlayer) {
GuiBase.getInterface().disableOverlay();
waitForUserInput = false;
aiMatchInProgress = true;
} else {
}
else {
waitForUserInput = true;
aiMatchInProgress = false;
}
@@ -205,10 +181,9 @@ public class QuestDraftUtils {
FThreads.invokeInEdtLater(new Runnable(){
@Override
public void run() {
Singletons.getControl().startGameWithUi(match);
GuiBase.getInterface().startGame(match);
}
});
}
public static void continueMatches() {
@@ -222,5 +197,4 @@ public class QuestDraftUtils {
private boolean hasHumanPlayer = false;
}
}

View File

@@ -17,18 +17,37 @@
*/
package forge.quest;
import forge.FThreads;
import forge.GuiBase;
import forge.LobbyPlayer;
import forge.assets.FSkinProp;
import forge.card.CardDb.SetPreference;
import forge.card.CardEdition;
import forge.card.CardRules;
import forge.deck.Deck;
import forge.game.GameRules;
import forge.game.GameType;
import forge.game.Match;
import forge.game.card.Card;
import forge.game.player.RegisteredPlayer;
import forge.interfaces.IButton;
import forge.item.IPaperCard;
import forge.item.PaperToken;
import forge.model.FModel;
import forge.properties.ForgePreferences.FPref;
import forge.quest.bazaar.QuestItemType;
import forge.quest.bazaar.QuestPetController;
import forge.quest.data.QuestAchievements;
import forge.quest.data.QuestAssets;
import forge.quest.data.QuestPreferences.QPref;
import forge.util.gui.SGuiChoose;
import forge.util.gui.SOptionPane;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
/**
* <p>
* QuestUtil class.
@@ -170,5 +189,480 @@ public class QuestUtil {
// Standard card creation
return FModel.getMagicDb().getCommonCards().getCardFromEdition(name, SetPreference.Latest);
}
public static void travelWorld() {
if (!checkActiveQuest("Travel between worlds.")) {
return;
}
List<QuestWorld> worlds = new ArrayList<QuestWorld>();
final QuestController qCtrl = FModel.getQuest();
for (QuestWorld qw : FModel.getWorlds()) {
if (qCtrl.getWorld() != qw) {
worlds.add(qw);
}
}
if (worlds.size() < 1) {
SOptionPane.showErrorDialog("There are currently no worlds you can travel to\nin this version of Forge.", "No Worlds");
return;
}
final String setPrompt = "Where do you wish to travel?";
final QuestWorld newWorld = SGuiChoose.oneOrNone(setPrompt, worlds);
if (worlds.indexOf(newWorld) < 0) {
return;
}
if (qCtrl.getWorld() != newWorld) {
boolean needRemove = false;
if (nextChallengeInWins() < 1 && qCtrl.getAchievements().getCurrentChallenges().size() > 0) {
needRemove = true;
if (!SOptionPane.showConfirmDialog(
"You have uncompleted challenges in your current world. If you travel now, they will be LOST!"
+ "\nAre you sure you wish to travel anyway?\n"
+ "(Click \"No\" to go back and complete your current challenges first.)",
"WARNING: Uncompleted challenges")) {
return;
}
}
if (needRemove) {
// Remove current challenges.
while (nextChallengeInWins() == 0) {
qCtrl.getAchievements().addChallengesPlayed();
}
qCtrl.getAchievements().getCurrentChallenges().clear();
}
qCtrl.setWorld(newWorld);
qCtrl.resetDuelsManager();
qCtrl.resetChallengesManager();
// Note that the following can be (ab)used to re-randomize your opponents by travelling to a different
// world and back. To prevent this, simply delete the following line that randomizes DuelsManager.
// (OTOH, you can 'swap' opponents even more easily by simply selecting a different quest data file and
// then re-selecting your current quest data file.)
qCtrl.getDuelsManager().randomizeOpponents();
qCtrl.getCards().clearShopList();
qCtrl.save();
}
}
private static QuestEvent event;
private static QuestEventDraft draftEvent;
/**
* <p>
* nextChallengeInWins.
* </p>
*
* @return a int.
*/
public static int nextChallengeInWins() {
final QuestController qData = FModel.getQuest();
final int challengesPlayed = qData.getAchievements().getChallengesPlayed();
final int wins = qData.getAchievements().getWin();
final int turnsToUnlock = FModel.getQuest().getTurnsToUnlockChallenge();
final int delta;
// First challenge unlocks after minimum wins reached.
if (wins < 2 * turnsToUnlock) {
delta = 2 * turnsToUnlock - wins;
}
else {
// More than enough wins
if (wins / turnsToUnlock > challengesPlayed) {
delta = 0;
}
// This part takes the "unlimited challenge" bug into account;
// a player could have an inflated challengesPlayed value.
// Added 09-2012, can be removed after a while.
else if (wins < challengesPlayed * turnsToUnlock) {
delta = (challengesPlayed * turnsToUnlock - wins) + turnsToUnlock;
}
// Data OK, but not enough wins yet (default).
else {
delta = turnsToUnlock - wins % turnsToUnlock;
}
}
return (delta > 0) ? delta : 0;
}
private static void updatePlantAndPetForView(final IVQuestStats view, final QuestController qCtrl) {
for (int iSlot = 0; iSlot < QuestController.MAX_PET_SLOTS; iSlot++) {
final List<QuestPetController> petList = qCtrl.getPetsStorage().getAvaliablePets(iSlot, qCtrl.getAssets());
final String currentPetName = qCtrl.getSelectedPet(iSlot);
if (iSlot == 0) { // Plant visiblity
if (petList.isEmpty()) {
view.getCbPlant().setVisible(false);
}
else {
view.getCbPlant().setVisible(true);
view.getCbPlant().setSelected(currentPetName != null);
}
}
if (iSlot == 1) {
view.getCbxPet().removeAllItems();
// Pet list visibility
if (petList.size() > 0) {
view.getCbxPet().setVisible(true);
view.getCbxPet().addItem("Don't summon a pet");
for (final QuestPetController pet : petList) {
String name = "Summon " + pet.getName();
view.getCbxPet().addItem(name);
if (pet.getName().equals(currentPetName)) {
view.getCbxPet().setSelectedItem(name);
}
}
} else {
view.getCbxPet().setVisible(false);
}
}
}
if (qCtrl.getAssets().hasItem(QuestItemType.CHARM)) {
view.getCbCharm().setVisible(true);
}
else {
view.getCbCharm().setVisible(false);
}
if (view.isChallengesView()) {
view.getLblZep().setVisible(qCtrl.getAssets().hasItem(QuestItemType.ZEPPELIN));
if (qCtrl.getAssets().getItemLevel(QuestItemType.ZEPPELIN) == 2) {
view.getLblZep().setEnabled(false);
view.getLblZep().setTextColor(128, 128, 128);
}
else {
view.getLblZep().setEnabled(true);
view.getLblZep().setTextColor(FSkinProp.CLR_TEXT);
}
}
else {
view.getLblZep().setVisible(false);
}
}
/**
* Updates all quest info in a view, using
* retrieval methods dictated in IVQuestStats.<br>
* - Stats<br>
* - Pets<br>
* - Current deck info<br>
* - "Challenge In" info<br>
*
* @param view0 {@link forge.screens.home.quest.IVQuestStats}
*/
public static void updateQuestView(final IVQuestStats view0) {
final QuestController qCtrl = FModel.getQuest();
final QuestAchievements qA = qCtrl.getAchievements();
final QuestAssets qS = qCtrl.getAssets();
if (qA == null) { return; }
// Fantasy UI display
view0.getLblNextChallengeInWins().setVisible(true);
view0.getBtnBazaar().setVisible(true);
view0.getLblLife().setVisible(true);
// Stats panel
view0.getLblCredits().setText("Credits: " + qS.getCredits());
view0.getLblLife().setText("Life: " + qS.getLife(qCtrl.getMode()));
view0.getLblWins().setText("Wins: " + qA.getWin());
view0.getLblLosses().setText("Losses: " + qA.getLost());
view0.getLblWorld().setText("World: " + (qCtrl.getWorld() == null ? "(none)" : qCtrl.getWorld()));
// Show or hide the set unlocking button
view0.getBtnUnlock().setVisible(qCtrl.getUnlocksTokens() > 0 && qCtrl.getWorldFormat() == null);
// Challenge in wins
final int num = nextChallengeInWins();
final String str;
if (num == 0) {
str = "Your exploits have been noticed. An opponent has challenged you.";
}
else if (num == 1) {
str = "A new challenge will be available after 1 more win.";
}
else {
str = "A new challenge will be available in " + num + " wins.";
}
view0.getLblNextChallengeInWins().setText(str);
view0.getLblWinStreak().setText(
"<html>Win streak: " + qA.getWinStreakCurrent()
+ "<br>&nbsp; (Best: " + qA.getWinStreakBest() + ")</html>");
// Current deck message
final IButton lblCurrentDeck = view0.getLblCurrentDeck();
if (getCurrentDeck() == null) {
lblCurrentDeck.setTextColor(204, 0, 0);
lblCurrentDeck.setText("Build, then select a deck in the \"Quest Decks\" submenu.");
}
else {
lblCurrentDeck.setTextColor(FSkinProp.CLR_TEXT);
lblCurrentDeck.setText("Your current deck is \""
+ getCurrentDeck().getName() + "\".");
}
// Start panel: pet, plant, zep.
if (qCtrl.getMode() == QuestMode.Fantasy) {
updatePlantAndPetForView(view0, qCtrl);
}
else {
// Classic mode display changes
view0.getCbxPet().setVisible(false);
view0.getCbPlant().setVisible(false);
view0.getCbCharm().setVisible(false);
view0.getLblZep().setVisible(false);
view0.getLblNextChallengeInWins().setVisible(false);
view0.getBtnBazaar().setVisible(false);
view0.getLblLife().setVisible(false);
}
}
/** @return {@link forge.deck.Deck} */
public static Deck getCurrentDeck() {
Deck d = null;
if (FModel.getQuest().getAssets() != null) {
d = FModel.getQuest().getMyDecks().get(
FModel.getQuestPreferences().getPref(QPref.CURRENT_DECK));
}
return d;
}
/** Updates the current selected quest event, used when game is started.
* @param event0 {@link forge.quest.QuestEvent}
*/
public static void setEvent(final QuestEvent event0) {
event = event0;
}
public static void setDraftEvent(final QuestEventDraft event0) {
draftEvent = event0;
}
public static QuestEventDraft getDraftEvent() {
return draftEvent;
}
public static boolean checkActiveQuest(String location) {
QuestController qc = FModel.getQuest();
if (qc == null || qc.getAssets() == null) {
String msg = "Please create a Quest before attempting to " + location;
SOptionPane.showErrorDialog(msg, "No Quest");
System.out.println(msg);
return false;
}
return true;
}
/** */
public static void showSpellShop() {
if (!checkActiveQuest("Visit the Spell Shop.")) {
return;
}
GuiBase.getInterface().showSpellShop();
}
/** */
public static void showBazaar() {
if (!checkActiveQuest("Visit the Bazaar.")) {
return;
}
GuiBase.getInterface().showBazaar();
}
/** */
public static void chooseAndUnlockEdition() {
if (!checkActiveQuest("Unlock Editions.")) {
return;
}
final QuestController qData = FModel.getQuest();
ImmutablePair<CardEdition, Integer> toUnlock = QuestUtilUnlockSets.chooseSetToUnlock(qData, false, null);
if (toUnlock == null) {
return;
}
CardEdition unlocked = toUnlock.left;
qData.getAssets().subtractCredits(toUnlock.right);
SOptionPane.showMessageDialog("You have successfully unlocked " + unlocked.getName() + "!",
unlocked.getName() + " unlocked!", null);
QuestUtilUnlockSets.doUnlock(qData, unlocked);
}
/** */
public static void startGame() {
if (!checkActiveQuest("Start a duel.") || null == event) {
return;
}
final QuestController qData = FModel.getQuest();
Deck deck = null;
if (event instanceof QuestEventChallenge) {
// Predefined HumanDeck
deck = ((QuestEventChallenge) event).getHumanDeck();
}
if (deck == null) {
// If no predefined Deck, use the Player's Deck
deck = getCurrentDeck();
}
if (deck == null) {
String msg = "Please select a Quest Deck.";
SOptionPane.showErrorDialog(msg, "No Deck");
System.out.println(msg);
return;
}
if (FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) {
String errorMessage = GameType.Quest.getDecksFormat().getDeckConformanceProblem(deck);
if (null != errorMessage) {
SOptionPane.showErrorDialog("Your deck " + errorMessage + " Please edit or choose a different deck.", "Invalid Deck");
return;
}
}
FThreads.invokeInBackgroundThread(new Runnable() {
@Override
public void run() {
qData.getDuelsManager().randomizeOpponents();
qData.setCurrentEvent(event);
qData.save();
}
});
int extraLifeHuman = 0;
Integer lifeHuman = null;
boolean useBazaar = true;
Boolean forceAnte = null;
int lifeAI = 20;
if (event instanceof QuestEventChallenge) {
QuestEventChallenge qc = ((QuestEventChallenge) event);
lifeAI = qc.getAILife();
lifeHuman = qc.getHumanLife();
if (qData.getAssets().hasItem(QuestItemType.ZEPPELIN)) {
extraLifeHuman = 3;
}
useBazaar = qc.isUseBazaar();
forceAnte = qc.isForceAnte();
}
RegisteredPlayer humanStart = new RegisteredPlayer(deck);
RegisteredPlayer aiStart = new RegisteredPlayer(event.getEventDeck());
if (lifeHuman != null) {
humanStart.setStartingLife(lifeHuman);
} else {
humanStart.setStartingLife(qData.getAssets().getLife(qData.getMode()) + extraLifeHuman);
}
if (useBazaar) {
humanStart.setCardsOnBattlefield(QuestUtil.getHumanStartingCards(qData, event));
aiStart.setStartingLife(lifeAI);
aiStart.setCardsOnBattlefield(QuestUtil.getComputerStartingCards(event));
}
List<RegisteredPlayer> starter = new ArrayList<RegisteredPlayer>();
starter.add(humanStart.setPlayer(GuiBase.getInterface().getQuestPlayer()));
LobbyPlayer aiPlayer = GuiBase.getInterface().getAiPlayer(event.getOpponent() == null ? event.getTitle() : event.getOpponent());
GuiBase.getInterface().setPlayerAvatar(aiPlayer, event.getIconImageKey());
starter.add(aiStart.setPlayer(aiPlayer));
boolean useRandomFoil = FModel.getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL);
for(RegisteredPlayer rp : starter) {
rp.setRandomFoil(useRandomFoil);
}
boolean useAnte = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE);
boolean matchAnteRarity = FModel.getPreferences().getPrefBoolean(FPref.UI_ANTE_MATCH_RARITY);
if(forceAnte != null)
useAnte = forceAnte.booleanValue();
GameRules rules = new GameRules(GameType.Quest);
rules.setPlayForAnte(useAnte);
rules.setMatchAnteRarity(matchAnteRarity);
rules.setGamesPerMatch(qData.getCharmState() ? 5 : 3);
rules.setManaBurn(FModel.getPreferences().getPrefBoolean(FPref.UI_MANABURN));
rules.canCloneUseTargetsImage = FModel.getPreferences().getPrefBoolean(FPref.UI_CLONE_MODE_SOURCE);
final Match mc = new Match(rules, starter);
FThreads.invokeInEdtLater(new Runnable(){
@Override
public void run() {
GuiBase.getInterface().startGame(mc);
}
});
}
/**
* Checks to see if a game can be started and displays relevant dialogues.
* @return
*/
public static boolean canStartGame() {
if (!checkActiveQuest("Start a duel.") || null == event) {
return false;
}
Deck deck = null;
if (event instanceof QuestEventChallenge) {
// Predefined HumanDeck
deck = ((QuestEventChallenge) event).getHumanDeck();
}
if (deck == null) {
// If no predefined Deck, use the Player's Deck
deck = getCurrentDeck();
}
if (deck == null) {
String msg = "Please select a Quest Deck.";
SOptionPane.showErrorDialog(msg, "No Deck");
System.out.println(msg);
return false;
}
if (FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) {
String errorMessage = GameType.Quest.getDecksFormat().getDeckConformanceProblem(deck);
if (null != errorMessage) {
SOptionPane.showErrorDialog("Your deck " + errorMessage + " Please edit or choose a different deck.", "Invalid Deck");
return false;
}
}
return true;
}
/** Duplicate in DeckEditorQuestMenu and
* probably elsewhere...can streamline at some point
* (probably shouldn't be here).
*
* @param in &emsp; {@link java.lang.String}
* @return {@link java.lang.String}
*/
public static String cleanString(final String in) {
final StringBuffer out = new StringBuffer();
final char[] c = in.toCharArray();
for (int i = 0; (i < c.length) && (i < 20); i++) {
if (Character.isLetterOrDigit(c[i]) || (c[i] == '-') || (c[i] == '_') || (c[i] == ' ')) {
out.append(c[i]);
}
}
return out.toString();
}
} // QuestUtil