Erwan
- Added AI Decks unlock system. Please update your graphics folder, and crossing fingers that Ilya B. is still around as I don't have the correct fonts.
This commit is contained in:
BIN
projects/mtg/bin/Res/graphics/ai_unlocked.png
Normal file
BIN
projects/mtg/bin/Res/graphics/ai_unlocked.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
projects/mtg/bin/Res/graphics/new.png
Normal file
BIN
projects/mtg/bin/Res/graphics/new.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 KiB |
@@ -25,10 +25,11 @@ public:
|
||||
class Credits{
|
||||
private:
|
||||
time_t gameLength;
|
||||
int isDifficultyUnlocked();
|
||||
int isDifficultyUnlocked(DeckStats * stats);
|
||||
int isMomirUnlocked();
|
||||
int isEvilTwinUnlocked();
|
||||
int isRandomDeckUnlocked();
|
||||
int IsMoreAIDecksUnlocked(DeckStats * stats);
|
||||
public:
|
||||
int value;
|
||||
Player * p1, *p2;
|
||||
|
||||
@@ -38,6 +38,8 @@ public:
|
||||
int percentVictories(string opponentsDeckFile);
|
||||
int percentVictories();
|
||||
DeckStat * getDeckStat(string opponentsFile);
|
||||
|
||||
//returns the total number of games played with this deck
|
||||
int nbGames();
|
||||
};
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
GUI_STYLE,
|
||||
INTERRUPT_SECONDS,
|
||||
KEY_BINDINGS,
|
||||
AIDECKS_UNLOCKED,
|
||||
//My interrupts
|
||||
INTERRUPTMYSPELLS,
|
||||
INTERRUPTMYABILITIES,
|
||||
@@ -75,7 +76,7 @@ public:
|
||||
MOMIR_MODE_UNLOCKED,
|
||||
EVILTWIN_MODE_UNLOCKED,
|
||||
RANDOMDECK_MODE_UNLOCKED,
|
||||
AWARD_COLLECTOR,
|
||||
AWARD_COLLECTOR,
|
||||
LAST_NAMED, //Any option after this does not look up in optionNames.
|
||||
SET_UNLOCKS = LAST_NAMED + 1, //For sets.
|
||||
};
|
||||
|
||||
@@ -69,10 +69,11 @@ class GameState
|
||||
static vector<DeckMetaData *> fillDeckMenu(SimpleMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL);
|
||||
|
||||
// generate the Deck Meta Data and build the menu items of the menu given
|
||||
static vector<DeckMetaData *> fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL);
|
||||
// Will display up to maxDecks if maxDecks is non 0,all decks in path otherwise
|
||||
static vector<DeckMetaData *> fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0);
|
||||
|
||||
// build a vector of decks with the information passsed in.
|
||||
static vector<DeckMetaData *> getValidDeckMetaData(const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL);
|
||||
static vector<DeckMetaData *> getValidDeckMetaData(const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0);
|
||||
|
||||
// build menu items based on the vector<DeckMetaData *>
|
||||
static void renderDeckMenu(SimpleMenu * _menu, const vector<DeckMetaData *>& deckMetaDataList);
|
||||
|
||||
@@ -978,9 +978,10 @@ AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, Player * op
|
||||
{
|
||||
if (!deckid)
|
||||
{
|
||||
//random deck
|
||||
int nbdecks = 0;
|
||||
int found = 1;
|
||||
while (found)
|
||||
while (found && nbdecks < options[Options::AIDECKS_UNLOCKED].number)
|
||||
{
|
||||
found = 0;
|
||||
char buffer[512];
|
||||
|
||||
@@ -119,7 +119,9 @@ void Credits::compute(Player * _p1, Player * _p2, GameApp * _app)
|
||||
|
||||
if (unlocked == -1)
|
||||
{
|
||||
unlocked = isDifficultyUnlocked();
|
||||
DeckStats * stats = DeckStats::GetInstance();
|
||||
stats->load(p1);
|
||||
unlocked = isDifficultyUnlocked(stats);
|
||||
if (unlocked)
|
||||
{
|
||||
unlockedTex = resources.RetrieveTexture("unlocked.png");
|
||||
@@ -160,6 +162,12 @@ void Credits::compute(Player * _p1, Player * _p2, GameApp * _app)
|
||||
if (si)
|
||||
unlockedString = si->getName(); //Show the set's pretty name for unlocks.
|
||||
}
|
||||
else if ((unlocked = IsMoreAIDecksUnlocked(stats)))
|
||||
{
|
||||
options[Options::AIDECKS_UNLOCKED].number += 10;
|
||||
unlockedTex = resources.RetrieveTexture("ai_unlocked.png");
|
||||
unlockedQuad = resources.RetrieveQuad("ai_unlocked.png", 2, 2, 396, 96);
|
||||
}
|
||||
|
||||
if (unlocked && options[Options::SFXVOLUME].number > 0)
|
||||
{
|
||||
@@ -292,15 +300,14 @@ void Credits::Render()
|
||||
|
||||
}
|
||||
|
||||
int Credits::isDifficultyUnlocked()
|
||||
int Credits::isDifficultyUnlocked(DeckStats * stats)
|
||||
{
|
||||
if (options[Options::DIFFICULTY_MODE_UNLOCKED].number)
|
||||
return 0;
|
||||
int nbAIDecks = 0;
|
||||
int found = 1;
|
||||
int wins = 0;
|
||||
DeckStats * stats = DeckStats::GetInstance();
|
||||
stats->load(p1);
|
||||
|
||||
while (found)
|
||||
{
|
||||
found = 0;
|
||||
@@ -424,3 +431,31 @@ int Credits::unlockRandomSet(bool force)
|
||||
options.save();
|
||||
return setId + 1; //We add 1 here to show success/failure. Be sure to subtract later.
|
||||
}
|
||||
|
||||
|
||||
int Credits::IsMoreAIDecksUnlocked(DeckStats * stats) {
|
||||
int currentlyUnlocked = options[Options::AIDECKS_UNLOCKED].number;
|
||||
|
||||
// Random rule: having played at least twice as much games as
|
||||
// the number of currently unlocked decks in order to go through.
|
||||
if (stats->nbGames() < currentlyUnlocked * 2) return 0;
|
||||
|
||||
int nbdecks = 0;
|
||||
int found = 1;
|
||||
while (found)
|
||||
{
|
||||
found = 0;
|
||||
char buffer[512];
|
||||
sprintf(buffer, JGE_GET_RES("ai/baka/deck%i.txt").c_str(), nbdecks + 1);
|
||||
std::ifstream file(buffer);
|
||||
if (file)
|
||||
{
|
||||
found = 1;
|
||||
file.close();
|
||||
nbdecks++;
|
||||
if (nbdecks > currentlyUnlocked)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -336,5 +336,4 @@ DeckMenu::~DeckMenu()
|
||||
{
|
||||
resources.Release(pspIconsTexture);
|
||||
SAFE_DELETE(mScroller);
|
||||
mScroller = NULL;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "DeckMenuItem.h"
|
||||
#include "Translate.h"
|
||||
#include "WResourceManager.h"
|
||||
#include <algorithm>
|
||||
|
||||
#define ITEM_PX_WIDTH 190.f
|
||||
const int kHorizontalScrollSpeed = 10; // lower numbers mean faster scrolling
|
||||
@@ -62,6 +63,19 @@ void DeckMenuItem::RenderWithOffset(float yOffset)
|
||||
mScrollTimer = 0;
|
||||
else if (mHasFocus && mScrollEnabled)
|
||||
mScrollTimer++;
|
||||
|
||||
//Render a "new" icon for decks that have never been played yet
|
||||
if (meta && !meta->getGamesPlayed())
|
||||
{
|
||||
JTexture * tex = resources.RetrieveTexture("new.png");
|
||||
if (tex)
|
||||
{
|
||||
JQuad * quad = resources.RetrieveQuad("new.png", 2, 2, tex->mWidth - 4, tex->mHeight - 4); //avoids weird rectangle aroudn the texture because of bilinear filtering
|
||||
quad->SetHotSpot(quad->mWidth/2, quad->mHeight/2);
|
||||
float x = mX + min(ITEM_PX_WIDTH - quad->mWidth, mFont->GetStringWidth(menuItemString.c_str()))/2 + quad->mWidth/2;
|
||||
if (quad) JRenderer::GetInstance()->RenderQuad(quad, x , mY + yOffset + quad->mHeight/2, 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeckMenuItem::Render()
|
||||
|
||||
@@ -39,6 +39,7 @@ const string Options::optionNames[] = {
|
||||
"keybindings_psp",
|
||||
#endif
|
||||
#endif
|
||||
"aidecks",
|
||||
"interruptMySpells",
|
||||
"interruptMyAbilities",
|
||||
//General interrupts
|
||||
@@ -342,6 +343,9 @@ int GameOptions::load()
|
||||
if (!(*this)[Options::MAX_GRADE].number)
|
||||
(*this)[Options::MAX_GRADE].number = Constants::GRADE_BORDERLINE;
|
||||
|
||||
if (!(*this)[Options::AIDECKS_UNLOCKED].number)
|
||||
(*this)[Options::AIDECKS_UNLOCKED].number = 10;
|
||||
|
||||
return 1;
|
||||
}
|
||||
int GameOptions::save()
|
||||
|
||||
@@ -26,25 +26,25 @@ vector<DeckMetaData *> GameState::fillDeckMenu(SimpleMenu * _menu, const string&
|
||||
}
|
||||
|
||||
vector<DeckMetaData *> GameState::fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix,
|
||||
Player * statsPlayer)
|
||||
Player * statsPlayer, int maxDecks)
|
||||
{
|
||||
bool translate = _menu->mAutoTranslate;
|
||||
_menu->mAutoTranslate = false;
|
||||
vector<DeckMetaData *> deckMetaDataVector = getValidDeckMetaData(path, smallDeckPrefix, statsPlayer);
|
||||
vector<DeckMetaData *> deckMetaDataVector = getValidDeckMetaData(path, smallDeckPrefix, statsPlayer, maxDecks);
|
||||
renderDeckMenu(_menu, deckMetaDataVector);
|
||||
_menu->mAutoTranslate = translate;
|
||||
|
||||
return deckMetaDataVector;
|
||||
}
|
||||
|
||||
vector<DeckMetaData *> GameState::getValidDeckMetaData(const string& path, const string& smallDeckPrefix, Player * statsPlayer)
|
||||
vector<DeckMetaData *> GameState::getValidDeckMetaData(const string& path, const string& smallDeckPrefix, Player * statsPlayer, int maxDecks)
|
||||
{
|
||||
vector<DeckMetaData*> retList;
|
||||
|
||||
DeckMetaDataList * metas = DeckMetaDataList::decksMetaData;
|
||||
int found = 1;
|
||||
int nbDecks = 1;
|
||||
while (found)
|
||||
while (found && (!maxDecks || nbDecks <= maxDecks))
|
||||
{
|
||||
found = 0;
|
||||
std::ostringstream filename;
|
||||
|
||||
@@ -283,7 +283,7 @@ void GameStateDuel::ensureOpponentMenu()
|
||||
if (options[Options::EVILTWIN_MODE_UNLOCKED].number) opponentMenu->Add(MENUITEM_EVIL_TWIN, "Evil Twin", _(
|
||||
"Can you play against yourself?").c_str());
|
||||
DeckManager * deckManager = DeckManager::GetInstance();
|
||||
vector<DeckMetaData*> opponentDeckList = fillDeckMenu(opponentMenu, JGE_GET_RES("ai/baka"), "ai_baka", mPlayers[0]);
|
||||
vector<DeckMetaData*> opponentDeckList = fillDeckMenu(opponentMenu, JGE_GET_RES("ai/baka"), "ai_baka", mPlayers[0], options[Options::AIDECKS_UNLOCKED].number);
|
||||
deckManager->updateMetaDataList(&opponentDeckList, true);
|
||||
opponentMenu->Add(MENUITEM_CANCEL, "Cancel", _("Choose a different player deck").c_str());
|
||||
opponentDeckList.clear();
|
||||
|
||||
@@ -189,9 +189,13 @@ void Task::passOneDay()
|
||||
|
||||
void Task::loadAIDeckNames()
|
||||
{
|
||||
//check if cache is up to date
|
||||
if (AIDeckNames.size() == (unsigned int)(options[Options::AIDECKS_UNLOCKED].number)) return;
|
||||
|
||||
AIDeckNames.clear();
|
||||
int found = 1;
|
||||
int nbDecks = 0;
|
||||
while (found)
|
||||
while (found && nbDecks < options[Options::AIDECKS_UNLOCKED].number)
|
||||
{
|
||||
found = 0;
|
||||
char buffer[512];
|
||||
@@ -211,19 +215,13 @@ void Task::loadAIDeckNames()
|
||||
|
||||
int Task::getAIDeckCount()
|
||||
{
|
||||
if (AIDeckNames.size() == 0)
|
||||
{
|
||||
loadAIDeckNames();
|
||||
}
|
||||
loadAIDeckNames();
|
||||
return AIDeckNames.size();
|
||||
}
|
||||
|
||||
string Task::getAIDeckName(int id)
|
||||
{
|
||||
if (AIDeckNames.size() == 0)
|
||||
{
|
||||
loadAIDeckNames();
|
||||
}
|
||||
loadAIDeckNames();
|
||||
return ((unsigned int) id <= AIDeckNames.size()) ? AIDeckNames.at(id - 1) : "<Undefined>";
|
||||
}
|
||||
|
||||
|
||||
@@ -265,39 +265,39 @@ std::string wordWrap(std::string sentence, int width)
|
||||
// Given a delimited string of abilities, add the ones to the list that are "Basic" MTG abilities
|
||||
void PopulateAbilityIndexVector( list<int>& abilities, const string& abilityStringList, char delimiter )
|
||||
{
|
||||
vector<string> abilitiesList = split( abilityStringList, delimiter);
|
||||
for ( vector<string>::iterator iter = abilitiesList.begin(); iter != abilitiesList.end(); ++iter)
|
||||
{
|
||||
int abilityIndex = Constants::GetBasicAbilityIndex( *iter );
|
||||
|
||||
if (abilityIndex != -1)
|
||||
abilities.push_back( abilityIndex );
|
||||
vector<string> abilitiesList = split( abilityStringList, delimiter);
|
||||
for ( vector<string>::iterator iter = abilitiesList.begin(); iter != abilitiesList.end(); ++iter)
|
||||
{
|
||||
int abilityIndex = Constants::GetBasicAbilityIndex( *iter );
|
||||
|
||||
if (abilityIndex != -1)
|
||||
abilities.push_back( abilityIndex );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PopulateColorIndexVector( list<int>& colors, const string& colorStringList, char delimiter )
|
||||
{
|
||||
vector<string> abilitiesList = split( colorStringList, delimiter);
|
||||
for ( vector<string>::iterator iter = abilitiesList.begin(); iter != abilitiesList.end(); ++iter)
|
||||
{
|
||||
for (int colorIndex = Constants::MTG_COLOR_ARTIFACT; colorIndex < Constants::MTG_NB_COLORS; ++colorIndex)
|
||||
{
|
||||
// if the text is not a basic ability but contains a valid color add it to the color vector
|
||||
if ( (Constants::GetBasicAbilityIndex( *iter ) != -1) && ((*iter).find( Constants::MTGColorStrings[ colorIndex ] ) != string::npos) )
|
||||
colors.push_back(colorIndex);
|
||||
}
|
||||
vector<string> abilitiesList = split( colorStringList, delimiter);
|
||||
for ( vector<string>::iterator iter = abilitiesList.begin(); iter != abilitiesList.end(); ++iter)
|
||||
{
|
||||
for (int colorIndex = Constants::MTG_COLOR_ARTIFACT; colorIndex < Constants::MTG_NB_COLORS; ++colorIndex)
|
||||
{
|
||||
// if the text is not a basic ability but contains a valid color add it to the color vector
|
||||
if ( (Constants::GetBasicAbilityIndex( *iter ) != -1) && ((*iter).find( Constants::MTGColorStrings[ colorIndex ] ) != string::npos) )
|
||||
colors.push_back(colorIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PopulateSubtypesIndexVector( list<int>& types, const string& subTypesStringList, char delimiter)
|
||||
{
|
||||
vector<string> subTypesList = split( subTypesStringList, delimiter);
|
||||
for (vector<string>::iterator it = subTypesList.begin(); it != subTypesList.end(); ++it)
|
||||
{
|
||||
string subtype = *it;
|
||||
size_t id = Subtypes::subtypesList->find( subtype );
|
||||
if ( id != string::npos )
|
||||
types.push_back(id);
|
||||
vector<string> subTypesList = split( subTypesStringList, delimiter);
|
||||
for (vector<string>::iterator it = subTypesList.begin(); it != subTypesList.end(); ++it)
|
||||
{
|
||||
string subtype = *it;
|
||||
size_t id = Subtypes::subtypesList->find( subtype );
|
||||
if ( id != string::npos )
|
||||
types.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user