Files
wagic/projects/mtg/src/GameStateDuel.cpp
T
wagic.the.homebrew e27cf56fa2 - Support for Zip Filesystem. It is now possible to zip the entire Res folder ("store" method preferred, zip so that the root of the zip has ai, player, etc...) in one single file for read only. Write access is done in another folder (hardcoded to be User/ for now, can be updated depending on platforms, etc...
-- zipFS has several limitations...
--- in a general way, seekg doesn't work... so getting a file's size needs to be done through JFileSystem.
--- getLine on files open with zipFS doesn't work so great. Not sure if it is a normal issue because files are open in binary or not... JFileSystem therefore offers a "readIntoString" function that needs to be used instead of the usual "getline" technique. However getLine can then be used on a stream connected to the string.

-- tested on Windows and PSP, I also made sure android still works, but haven't tested zip support on Android.
-- I tried to maintain backwards compatibility, but this might break on some platforms, if I broke some platforms and you can't find a way to fix them, please contact me and we'll figure something out
-- This removes wagic::ifstream. I didn't reimplement the securities that were involved in this, apologies for that. Might be useful to reimplement such securities in JFileSystem
-- I haven't tested options/profiles in a deep way, it is possible I broke that.
2011-08-21 09:04:59 +00:00

860 lines
26 KiB
C++

#include "PrecompiledHeader.h"
#include "DeckMenu.h"
#include "GameStateDuel.h"
#include "utils.h"
#include "AIPlayer.h"
#include "AIMomirPlayer.h"
#include "PlayerData.h"
#include "DeckStats.h"
#include "DeckManager.h"
#include "DeckMetaData.h"
#include "MTGRules.h"
#include "Credits.h"
#include "Translate.h"
#include "Rules.h"
#include "ModRules.h"
#ifdef TESTSUITE
#include "TestSuiteAI.h"
#endif
#ifdef NETWORK_SUPPORT
#include "NetworkPlayer.h"
#endif
#if defined (WIN32) || defined (LINUX)
#include <time.h>
#endif
const float MENU_FONT_SCALE = 1.0f;
enum ENUM_DUEL_STATE
{
DUEL_STATE_START,
DUEL_STATE_END,
DUEL_STATE_CHOOSE_DECK1,
DUEL_STATE_DECK1_DETAILED_INFO,
DUEL_STATE_DECK2_DETAILED_INFO,
DUEL_STATE_CHOOSE_DECK1_TO_2,
DUEL_STATE_CHOOSE_DECK2,
DUEL_STATE_CHOOSE_DECK2_TO_PLAY,
DUEL_STATE_ERROR_NO_DECK,
DUEL_STATE_CANCEL,
DUEL_STATE_PLAY,
DUEL_STATE_BACK_TO_MAIN_MENU,
DUEL_STATE_MENU,
#ifdef NETWORK_SUPPORT
DUEL_STATE_OPPONENT_WAIT,
#endif //NETWORK_SUPPORT
DUEL_STATE_ERROR
};
enum ENUM_DUEL_MENUS
{
DUEL_MENU_GAME_MENU,
DUEL_MENU_CHOOSE_DECK,
DUEL_MENU_CHOOSE_OPPONENT,
DUEL_MENU_DETAILED_DECK1_INFO,
DUEL_MENU_DETAILED_DECK2_INFO
};
int GameStateDuel::selectedPlayerDeckId = 0;
int GameStateDuel::selectedAIDeckId = 0;
GameStateDuel::GameStateDuel(GameApp* parent) :
GameState(parent)
{
for (int i = 0; i < 2; i++)
{
mPlayers[i] = NULL;
}
premadeDeck = false;
game = NULL;
deckmenu = NULL;
opponentMenu = NULL;
menu = NULL;
popupScreen = NULL;
#ifdef TESTSUITE
testSuite = NULL;
#endif
credits = NULL;
#ifdef NETWORK_SUPPORT
RegisterNetworkPlayers();
#endif //NETWORK_SUPPORT
}
GameStateDuel::~GameStateDuel()
{
End();
}
void GameStateDuel::Start()
{
JRenderer * renderer = JRenderer::GetInstance();
renderer->EnableVSync(true);
OpponentsDeckid = 0;
#ifdef TESTSUITE
SAFE_DELETE(testSuite);
testSuite = NEW TestSuite("test/_tests.txt",MTGCollection());
#endif
mGamePhase = DUEL_STATE_CHOOSE_DECK1;
credits = NEW Credits();
menu = NULL;
int decksneeded = 0;
for (int i = 0; i < 2; i++)
{
if (mParent->players[i] == PLAYER_TYPE_HUMAN)
{
//DeckManager::EndInstance();
decksneeded = 1;
deckmenu = NEW DeckMenu(DUEL_MENU_CHOOSE_DECK, this, Fonts::OPTION_FONT, "Choose a Deck",
GameStateDuel::selectedPlayerDeckId, true);
deckmenu->enableDisplayDetailsOverride();
DeckManager *deckManager = DeckManager::GetInstance();
vector<DeckMetaData *> playerDeckList = BuildDeckList(options.profileFile());
int nbDecks = playerDeckList.size();
if (nbDecks)
decksneeded = 0;
if (nbDecks > 1)
deckmenu->Add(MENUITEM_RANDOM_PLAYER, "Random", "Play with a random deck.");
renderDeckMenu(deckmenu, playerDeckList);
// save the changes to the player deck list maintained in DeckManager
deckManager->updateMetaDataList(&playerDeckList, false);
playerDeckList.clear();
break;
}
}
if (deckmenu)
{
if (decksneeded)
{
if (gModRules.general.hasDeckEditor())
{
//translate deck creating desc
Translator * t = Translator::GetInstance();
string desc = "Highly recommended to get\nthe full Wagic experience!";
map<string, string>::iterator it = t->deckValues.find("Create your Deck!");
if (it != t->deckValues.end())
desc = it->second;
deckmenu->Add(MENUITEM_NEW_DECK, "Create your Deck!", desc);
}
premadeDeck = true;
fillDeckMenu(deckmenu, "player/premade");
}
else if (gModRules.general.hasDeckEditor())
{
deckmenu->Add(MENUITEM_NEW_DECK, "New Deck...", "Create a new deck to play with.");
}
deckmenu->Add(MENUITEM_CANCEL, "Main Menu", "Return to Main Menu");
}
for (int i = 0; i < 2; ++i)
{
mPlayers[i] = NULL;
}
}
void GameStateDuel::loadPlayer(int playerId, int decknb, bool isAI, bool isNetwork)
{
if (decknb)
{
if (!isAI)
{ //Human Player
if(playerId == 0)
{
char deckFile[255];
if (premadeDeck)
sprintf(deckFile, "player/premade/deck%i.txt", decknb);
else
sprintf(deckFile, "%s/deck%i.txt", options.profileFile().c_str(), decknb);
char deckFileSmall[255];
sprintf(deckFileSmall, "player_deck%i", decknb);
mPlayers[playerId] = NEW HumanPlayer(deckFile, deckFileSmall);
#ifdef NETWORK_SUPPORT
if(isNetwork)
{
ProxyPlayer* mProxy;
mProxy = NEW ProxyPlayer(mPlayers[playerId], mParent->mpNetwork);
}
}
else
{ //Remote player
mPlayers[playerId] = NEW RemotePlayer(mParent->mpNetwork);
#endif //NETWORK_SUPPORT
}
}
else
{ //AI Player, chooses deck
AIPlayerFactory playerCreator;
Player * opponent = NULL;
if (playerId == 1) opponent = mPlayers[0];
mPlayers[playerId] = playerCreator.createAIPlayer(MTGCollection(), opponent, decknb);
}
}
else
{ //Random deck
AIPlayerFactory playerCreator;
Player * opponent = NULL;
if (playerId == 1) opponent = mPlayers[0];
mPlayers[playerId] = playerCreator.createAIPlayer(MTGCollection(), opponent);
}
}
void GameStateDuel::initRand(unsigned int seed)
{
if (!seed)
seed = static_cast<unsigned int>(time(0));
srand(seed);
}
#ifdef TESTSUITE
void GameStateDuel::loadTestSuitePlayers()
{
if (!testSuite) return;
initRand(testSuite->seed);
SAFE_DELETE(game);
for (int i = 0; i < 2; i++)
{
mPlayers[i] = NEW TestSuiteAI(testSuite, i);
}
mParent->gameType = testSuite->gameType;
GameObserver::Init(mPlayers, 2);
game = GameObserver::GetInstance();
game->startGame(mParent->rules);
if (mParent->gameType == GAME_TYPE_MOMIR)
{
game->addObserver(NEW MTGMomirRule(-1, MTGCollection()));
}
}
#endif
void GameStateDuel::End()
{
DebugTrace("Ending GameStateDuel");
#ifdef TRACK_OBJECT_USAGE
ObjectAnalytics::DumpStatistics();
#endif
JRenderer::GetInstance()->EnableVSync(false);
if (!premadeDeck && mPlayers[0] && mPlayers[1])
{ // save the stats for the game
mPlayers[0]->End();
}
else if ( !mPlayers[1] && mPlayers[0] )
// clean up player object
SAFE_DELETE( mPlayers[0] );
GameObserver::EndInstance(); // this will delete both player objects if a game has been played
game = NULL;
premadeDeck = false;
for (int i = 0; i < 2; i++)
{
mPlayers[i] = NULL;
}
SAFE_DELETE(credits);
SAFE_DELETE(menu);
SAFE_DELETE(opponentMenu);
SAFE_DELETE(deckmenu);
SAFE_DELETE(popupScreen);
#ifdef TESTSUITE
SAFE_DELETE(testSuite);
#endif
}
//TODO Move This to utils or ResourceManager. Don't we have more generic functions that can do that?
bool GameStateDuel::MusicExist(string FileName)
{
return FileExists(WResourceManager::Instance()->musicFile(FileName));
}
void GameStateDuel::ConstructOpponentMenu()
{
if (opponentMenu == NULL)
{
opponentMenu = NEW DeckMenu(DUEL_MENU_CHOOSE_OPPONENT, this, Fonts::OPTION_FONT, "Choose Opponent",
GameStateDuel::selectedAIDeckId, true);
opponentMenu->Add(MENUITEM_RANDOM_AI, "Random");
if (options[Options::EVILTWIN_MODE_UNLOCKED].number) opponentMenu->Add(MENUITEM_EVIL_TWIN, "Evil Twin",
_("Can you defeat yourself?").c_str());
DeckManager * deckManager = DeckManager::GetInstance();
vector<DeckMetaData*> opponentDeckList;
int nbUnlockedDecks = options[Options::CHEATMODEAIDECK].number ? 1000 : options[Options::AIDECKS_UNLOCKED].number;
opponentDeckList = fillDeckMenu(opponentMenu, "ai/baka", "ai_baka", mPlayers[0], nbUnlockedDecks);
deckManager->updateMetaDataList(&opponentDeckList, true);
opponentMenu->Add(MENUITEM_CANCEL, "Cancel", _("Choose a different player deck").c_str());
opponentDeckList.clear();
}
}
void GameStateDuel::Update(float dt)
{
switch (mGamePhase)
{
case DUEL_STATE_ERROR_NO_DECK:
if (JGE_BTN_OK == mEngine->ReadButton()) mParent->SetNextState(GAME_STATE_DECK_VIEWER);
break;
case DUEL_STATE_DECK1_DETAILED_INFO:
case DUEL_STATE_DECK2_DETAILED_INFO:
popupScreen->Update(dt);
break;
case DUEL_STATE_CHOOSE_DECK1:
if (!mParent->rules->canChooseDeck())
{
mGamePhase = DUEL_STATE_PLAY;
}
#ifdef TESTSUITE
else if (mParent->players[1] == PLAYER_TYPE_TESTSUITE)
{
if (testSuite && testSuite->loadNext())
{
loadTestSuitePlayers();
mGamePhase = DUEL_STATE_PLAY;
testSuite->pregameTests();
testSuite->initGame();
}
else
{
if (!game)
{
mGamePhase = DUEL_STATE_ERROR;
}
else
{
mGamePhase = DUEL_STATE_END;
}
}
}
#endif
else
{
if (mParent->players[0] == PLAYER_TYPE_HUMAN)
{
if (!popupScreen || popupScreen->isClosed()) deckmenu->Update(dt);
}
else
{
loadPlayer(0);
mGamePhase = DUEL_STATE_CHOOSE_DECK2;
}
}
break;
case DUEL_STATE_CHOOSE_DECK1_TO_2:
if (deckmenu->isClosed())
mGamePhase = DUEL_STATE_CHOOSE_DECK2;
else
deckmenu->Update(dt);
break;
case DUEL_STATE_CHOOSE_DECK2:
if (mParent->players[1] == PLAYER_TYPE_HUMAN)
deckmenu->Update(dt);
else
{
if (mParent->players[0] == PLAYER_TYPE_HUMAN)
{
ConstructOpponentMenu();
opponentMenu->Update(dt);
}
else
{
loadPlayer(1);
mGamePhase = DUEL_STATE_PLAY;
}
}
break;
case DUEL_STATE_CHOOSE_DECK2_TO_PLAY:
if (mParent->players[1] == PLAYER_TYPE_HUMAN)
{
if (deckmenu->isClosed())
mGamePhase = DUEL_STATE_PLAY;
else
deckmenu->Update(dt);
}
else
{
ConstructOpponentMenu();
if (opponentMenu->isClosed())
mGamePhase = DUEL_STATE_PLAY;
else
opponentMenu->Update(dt);
}
break;
case DUEL_STATE_PLAY:
if (!game)
{
GameObserver::Init(mPlayers, 2);
game = GameObserver::GetInstance();
game->startGame(mParent->rules);
if (mParent->gameType == GAME_TYPE_MOMIR)
{
game->addObserver(NEW MTGMomirRule(-1, MTGCollection()));
}
if (mParent->gameType == GAME_TYPE_STONEHEWER)
{
game->addObserver(NEW MTGStoneHewerRule(-1,MTGCollection()));
}
if (mParent->gameType == GAME_TYPE_HERMIT)
{
game->addObserver(NEW MTGHermitRule(-1));
}
//start of in game music code
musictrack = "";
//check opponent id and choose the music track based on it
if (OpponentsDeckid)
{
char temp[4096];
sprintf(temp, "ai_baka_music%i.mp3", OpponentsDeckid);
musictrack.assign(temp);
}
else if (mParent->gameType == GAME_TYPE_CLASSIC)
musictrack = "ai_baka_music.mp3";
else if (mParent->gameType == GAME_TYPE_MOMIR)
musictrack = "ai_baka_music_momir.mp3";
else if (mParent->gameType == GAME_TYPE_RANDOM1 || mParent->gameType == GAME_TYPE_RANDOM2) musictrack
= "ai_baka_music_random.mp3";
if (!MusicExist(musictrack)) musictrack = "ai_baka_music.mp3";
GameApp::playMusic(musictrack);
}
game->Update(dt);
//run a "post update" init call in the rules. This is for things such as Manapool, which gets emptied in the update
// That's mostly because of a legacy bug, where we use the update sequence for some things when we should use events (such as phase changes)
mParent->rules->postUpdateInit();
if (game->gameOver)
{
if (game->players[1]->playMode != Player::MODE_TEST_SUITE) credits->compute(game->players[0], game->players[1], mParent);
mGamePhase = DUEL_STATE_END;
#ifdef TESTSUITE
if (mParent->players[1] == PLAYER_TYPE_TESTSUITE)
{
if (testSuite->loadNext())
{
loadTestSuitePlayers();
mGamePhase = DUEL_STATE_PLAY;
testSuite->initGame();
}
else
mGamePhase = DUEL_STATE_END;
}
else
#endif
if (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU)
{
End();
Start();
}
}
if (mEngine->GetButtonClick(JGE_BTN_MENU))
{
if (!menu)
{
menu = NEW SimpleMenu(DUEL_MENU_GAME_MENU, this, Fonts::MENU_FONT, SCREEN_WIDTH / 2 - 100, 25,
game->players[1]->deckName.c_str());
int cardsinhand = game->currentPlayer->game->hand->nb_cards;
//almosthumane - mulligan
if ((game->turn < 1) && (cardsinhand != 0) && game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
&& game->currentPlayer->game->inPlay->nb_cards == 0 && game->currentPlayer->game->graveyard->nb_cards == 0
&& game->currentPlayer->game->exile->nb_cards == 0 && game->currentlyActing() == (Player*)game->currentPlayer) //1st Play Check
//IF there was no play at the moment automatically mulligan
{
menu->Add(MENUITEM_MULLIGAN, "Mulligan");
}
//END almosthumane - mulligan
menu->Add(MENUITEM_MAIN_MENU, "Back to main menu");
menu->Add(MENUITEM_CANCEL, "Cancel");
}
mGamePhase = DUEL_STATE_MENU;
}
break;
#ifdef NETWORK_SUPPORT
case DUEL_STATE_OPPONENT_WAIT:
{
if(mPlayers[1] && mPlayers[1]->game)
{ // Player loaded
menu->Close();
SAFE_DELETE(menu);
mGamePhase = DUEL_STATE_PLAY;
} else if(menu == NULL)
{
loadPlayer(1, 42/* 0 not good*/, false, true);
menu = NEW SimpleMenu(DUEL_STATE_OPPONENT_WAIT, this, Fonts::MENU_FONT, 150, 60);
if (menu)
{
menu->Add(MENUITEM_MAIN_MENU, "Back to main menu");
}
} else
{
menu->Update(dt);
}
}
break;
#endif //NETWORK_SUPPORT
case DUEL_STATE_MENU:
menu->Update(dt);
break;
case DUEL_STATE_CANCEL:
menu->Update(dt);
if (menu->isClosed())
{
mGamePhase = DUEL_STATE_PLAY;
SAFE_DELETE(menu);
}
break;
case DUEL_STATE_BACK_TO_MAIN_MENU:
if (menu)
{
menu->Update(dt);
if (menu->isClosed())
{
PlayerData * playerdata = NEW PlayerData(MTGCollection());
playerdata->taskList->passOneDay();
playerdata->taskList->save();
SAFE_DELETE(playerdata);
SAFE_DELETE(menu);
}
}
mParent->DoTransition(TRANSITION_FADE, GAME_STATE_MENU);
break;
default:
if (JGE_BTN_OK == mEngine->ReadButton()) mParent->SetNextState(GAME_STATE_MENU);
}
}
void GameStateDuel::Render()
{
WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT);
JRenderer * r = JRenderer::GetInstance();
r->ClearScreen(ARGB(0,0,0,0));
if (game) game->Render();
switch (mGamePhase)
{
case DUEL_STATE_END:
{
r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(200,0,0,0));
credits->Render();
#ifdef TESTSUITE
if (mParent->players[1] == PLAYER_TYPE_TESTSUITE)
{
r->ClearScreen(ARGB(255,0,0,0));
char buf[4096];
int nbFailed = testSuite->nbFailed;
int nbTests = testSuite->nbTests;
if (!nbFailed)
{
sprintf(buf, "All %i tests successful!", nbTests);
}
else
{
sprintf(buf, "%i tests out of %i FAILED!", nbFailed, nbTests);
}
mFont->SetColor(ARGB(255,255,255,255));
mFont->DrawString(buf,0,SCREEN_HEIGHT/2);
nbFailed = testSuite->nbAIFailed;
nbTests = testSuite->nbAITests;
if (nbTests)
{
if (!nbFailed)
{
sprintf(buf, "AI Tests: All %i tests successful!", nbTests);
}
else
{
sprintf(buf, "AI Tests: %i tests out of %i FAILED!", nbFailed, nbTests);
}
mFont->DrawString(buf,0,SCREEN_HEIGHT/2+20);
}
}
#endif
break;
}
case DUEL_STATE_ERROR:
{
r->ClearScreen(ARGB(200,0,0,0));
mFont->DrawString(_("AN ERROR OCCURRED, CHECK FILE NAMES").c_str(), 0, SCREEN_HEIGHT / 2);
break;
}
case DUEL_STATE_CHOOSE_DECK1:
case DUEL_STATE_CHOOSE_DECK1_TO_2:
case DUEL_STATE_CHOOSE_DECK2:
case DUEL_STATE_CHOOSE_DECK2_TO_PLAY:
case DUEL_STATE_DECK1_DETAILED_INFO:
case DUEL_STATE_DECK2_DETAILED_INFO:
if (mParent->gameType != GAME_TYPE_CLASSIC
#ifdef NETWORK_SUPPORT
&& mParent->gameType != GAME_TYPE_SLAVE
#endif //NETWORK_SUPPORT
&& mParent->gameType != GAME_TYPE_STONEHEWER
&& mParent->gameType != GAME_TYPE_HERMIT)
mFont->DrawString(_("LOADING DECKS").c_str(), 0, SCREEN_HEIGHT / 2);
else
{
if (opponentMenu)
opponentMenu->Render();
else if (deckmenu && !deckmenu->isClosed()) deckmenu->Render();
if (menu) menu->Render();
if (popupScreen && !popupScreen->isClosed()) popupScreen->Render();
}
break;
case DUEL_STATE_ERROR_NO_DECK:
mFont->DrawString(_("NO DECK AVAILABLE,").c_str(), 0, SCREEN_HEIGHT / 2);
mFont->DrawString(_("PRESS CIRCLE TO GO TO THE DECK EDITOR!").c_str(), 0, SCREEN_HEIGHT / 2 + 20);
break;
#ifdef NETWORK_SUPPORT
case DUEL_STATE_OPPONENT_WAIT:
if (menu) menu->Render();
break;
#endif //NETWORK_SUPPORT
case DUEL_STATE_MENU:
case DUEL_STATE_CANCEL:
case DUEL_STATE_BACK_TO_MAIN_MENU:
if (game)
{
r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(100,0,0,0));
char buffer[4096];
sprintf(buffer, _("Turn:%i").c_str(), game->turn);
mFont->SetColor(ARGB(255,255,255,255));
mFont->DrawString(buffer, SCREEN_WIDTH / 2, 0, JGETEXT_CENTER);
}
if (menu) menu->Render();
}
}
void GameStateDuel::ButtonPressed(int controllerId, int controlId)
{
int deckNumber = controlId;
DeckManager * deckManager = DeckManager::GetInstance();
int aiDeckSize = deckManager->getAIDeckOrderList()->size();
switch (controllerId)
{
case DUEL_MENU_DETAILED_DECK1_INFO:
if ((popupScreen || deckmenu->showDetailsScreen()))
{
DeckMetaData* selectedDeck = deckmenu->getSelectedDeck();
if (!popupScreen->isClosed())
{
popupScreen->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK1;
SAFE_DELETE( popupScreen );
}
else
{
popupScreen->Update(selectedDeck);
popupScreen->Render();
}
}
break;
case DUEL_MENU_DETAILED_DECK2_INFO:
if ((popupScreen || opponentMenu->showDetailsScreen()))
{
DeckMetaData* selectedDeck = opponentMenu->getSelectedDeck();
if (!popupScreen->isClosed())
{
popupScreen->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY;
SAFE_DELETE( popupScreen );
}
else
{
popupScreen->Update(selectedDeck);
popupScreen->Render();
}
}
break;
case DUEL_MENU_CHOOSE_OPPONENT:
switch (controlId)
{
case MENUITEM_RANDOM_AI:
loadPlayer(1);
opponentMenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY;
break;
default:
// cancel option. return to player deck selection
if (controlId == MENUITEM_CANCEL)
{
opponentMenu->Close();
deckmenu->Close();
mParent->SetNextState(DUEL_STATE_CHOOSE_DECK1);
mGamePhase = DUEL_STATE_CHOOSE_DECK1;
break;
}
else if (controlId == MENUITEM_MORE_INFO && opponentMenu->showDetailsScreen())
{
DeckMetaData* selectedDeck = opponentMenu->getSelectedDeck();
if (!popupScreen)
{
popupScreen = NEW SimplePopup(DUEL_MENU_DETAILED_DECK2_INFO, this, Fonts::MAIN_FONT, "Detailed Information",
selectedDeck, MTGCollection());
popupScreen->Render();
selectedAIDeckId = selectedDeck->getDeckId();
}
else
{
popupScreen->Update(selectedDeck);
}
mGamePhase = DUEL_STATE_DECK2_DETAILED_INFO;
break;
}
else if (controlId == MENUITEM_MORE_INFO && !opponentMenu->showDetailsScreen())
{
// do nothing, ignore all key requests until popup is dismissed.
break;
}
else if (controlId != MENUITEM_EVIL_TWIN && aiDeckSize > 0) // evil twin
deckNumber = deckManager->getAIDeckOrderList()->at(controlId - 1)->getDeckId();
loadPlayer(1, deckNumber, 1);
OpponentsDeckid = deckNumber;
opponentMenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY;
break;
}
break;
case DUEL_MENU_CHOOSE_DECK:
if (controlId == MENUITEM_RANDOM_PLAYER) // Random Player Deck Selection
{
vector<DeckMetaData *> * playerDeckList = deckManager->getPlayerDeckOrderList();
deckNumber = playerDeckList->at(WRand() % (playerDeckList->size()))->getDeckId();
loadPlayer(0, deckNumber);
deckmenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY;
break;
}
else if (controlId == MENUITEM_MAIN_MENU || controlId == MENUITEM_CANCEL) // user clicked on "Cancel"
{
if (deckmenu) deckmenu->Close();
mGamePhase = DUEL_STATE_BACK_TO_MAIN_MENU;
break;
}
else if (controlId == MENUITEM_MORE_INFO && deckmenu->showDetailsScreen())
{
DeckMetaData* selectedDeck = deckmenu->getSelectedDeck();
if (!popupScreen)
{
popupScreen = NEW SimplePopup(DUEL_MENU_DETAILED_DECK1_INFO, this, Fonts::MAIN_FONT, "Detailed Information",
selectedDeck, MTGCollection());
popupScreen->Render();
selectedPlayerDeckId = deckmenu->getSelectedDeckId();
}
else
{
popupScreen->Update(selectedDeck);
}
mGamePhase = DUEL_STATE_DECK1_DETAILED_INFO;
break;
}
else if (controlId == MENUITEM_MORE_INFO)
{
// do nothing
break;
}
if (controlId < 0)
{
mParent->SetNextState(GAME_STATE_DECK_VIEWER);
return;
}
if (mGamePhase == DUEL_STATE_CHOOSE_DECK1)
{
vector<DeckMetaData *> * playerDeck = deckManager->getPlayerDeckOrderList();
if (!premadeDeck && controlId > 0)
deckNumber = playerDeck->at(controlId - 1)->getDeckId();
loadPlayer(0, deckNumber, false
#ifdef NETWORK_SUPPORT
,(mParent->players[1] == PLAYER_TYPE_REMOTE)
#endif //NETWORK_SUPPORT
);
deckmenu->Close();
#ifdef NETWORK_SUPPORT
if(mParent->players[1] == PLAYER_TYPE_REMOTE)
{ // no need to choose an opponent deck in network mode
mGamePhase = DUEL_STATE_OPPONENT_WAIT;
}
else
#endif //NETWORK_SUPPORT
{
mGamePhase = DUEL_STATE_CHOOSE_DECK1_TO_2;
}
playerDeck = NULL;
}
else
{
loadPlayer(1, controlId);
deckmenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY;
}
break;
default:
switch (controlId)
{
case MENUITEM_MAIN_MENU:
menu->Close();
mGamePhase = DUEL_STATE_BACK_TO_MAIN_MENU;
break;
case MENUITEM_CANCEL:
menu->Close();
mGamePhase = DUEL_STATE_CANCEL;
break;
case MENUITEM_MULLIGAN:
//almosthumane - mulligan
game->currentPlayer->takeMulligan();
menu->Close();
mGamePhase = DUEL_STATE_CANCEL;
break;
//END almosthumane - mulligan
}
}
}
void GameStateDuel::OnScroll(int inXVelocity, int inYVelocity)
{
if (abs(inYVelocity) > 300)
{
bool flickUpwards = (inYVelocity < 0);
mEngine->HoldKey_NoRepeat(flickUpwards ? JGE_BTN_PREV : JGE_BTN_SEC);
}
}