Jeck - Profile and cache improvements, booster duplicate likelihood reduced.

* Cache now tracks missing textures for RetrieveQuad, not just RetrieveCard/RetrieveTexture.
* Profile options are no longer overwritten when switching profiles.
* Main menu notifies of alternate profile- "Database: X" becomes "Profile: Y of X cards."
* Boosters iterates through cards, replacing duplicates. Stops after 15 tries to prevent infinite loops on small sets.
* Very simplistic theme switcher, only displays when alternate themes are present.
This commit is contained in:
wagic.jeck
2009-09-08 03:23:19 +00:00
parent a0b1da9810
commit ad7006e2de
9 changed files with 145 additions and 49 deletions

View File

@@ -75,6 +75,7 @@ public:
string str;
//All calls to asColor should include a fallback color for people without a theme.
PIXEL_TYPE asColor(PIXEL_TYPE fallback = ARGB(255,255,255,255));
bool isDefault(); //Returns true when number is 0 abd string is "" or "default"
GameOption(int value = 0);
GameOption(string value);
};

View File

@@ -24,6 +24,7 @@ public:
string displayValue, id;
int hasFocus;
bool canSelect;
bool bHidden;
float x, y;
float width, height;
virtual ostream& toString(ostream& out)const;
@@ -31,6 +32,7 @@ public:
OptionItem( string _id, string _displayValue);
virtual ~OptionItem() {};
virtual bool Selectable() {return (canSelect && !bHidden);};
virtual void Entering();
virtual bool Leaving();
virtual void Update(float dt);
@@ -69,6 +71,7 @@ class OptionString:public OptionItem{
virtual ostream& toString(ostream& out) const;
bool bShowValue;
};
class OptionNewProfile:public OptionString{
public:
OptionNewProfile(string _id, string _displayValue) : OptionString(_id, _displayValue) {bShowValue=false;};
@@ -118,6 +121,11 @@ private:
string root;
};
class OptionTheme:public OptionDirectory{
public:
OptionTheme();
};
class OptionProfile:public OptionDirectory{
public:
OptionProfile(GameApp * _app);

View File

@@ -7,7 +7,7 @@
#include "MTGCard.h"
#define CACHE_SIZE_PIXELS 2000000
#define MAX_CACHE_OBJECTS 100
#define MAX_CACHE_OBJECTS 200
class WCachedResource{
public:
@@ -84,6 +84,7 @@ public:
void ClearMisses();
void ClearUnlocked();
void ClearSamples();
void Refresh(); //Refreshes all files in cache, for when mode/profile changes.
unsigned int nowTime();
@@ -111,7 +112,6 @@ private:
bool RemoveOldestTexture();
bool RemoveOldestSample();
bool cleanup();
void clearSamples();
WCachedTexture * getCachedTexture(string filename, bool makenew = true, int mode = 0, int format = TEXTURE_FORMAT);
WCachedTexture * getCachedCard(MTGCard * card, int type = CACHE_CARD, bool makenew = true);
@@ -121,6 +121,8 @@ private:
//For cached stuff
map<string,WCachedTexture*> textureCache;
map<string,WCachedSample*> sampleCache;
vector<string> mTextureMissing; //For managed textures.
//Current access time.
int lastTime;

View File

@@ -77,6 +77,19 @@ const string Metrics::KEYPAD_TC = "_tKeypadTC";
GameOption::GameOption(int value) : number(value){}
GameOption::GameOption(string value) : str(value){}
bool GameOption::isDefault(){
if(number != 0)
return false;
string test = str;
std::transform(test.begin(),test.end(),test.begin(),::tolower);
if(!test.size() || test == "default")
return true;
return false;
}
PIXEL_TYPE GameOption::asColor(PIXEL_TYPE fallback)
{
unsigned char color[4];
@@ -177,14 +190,9 @@ GameSettings::GameSettings()
//Load global options
globalOptions = NEW GameOptions(GLOBAL_SETTINGS);
//Load profile options.
string temp = (*globalOptions)[Options::ACTIVE_PROFILE.substr(2)].str;
if(temp == "")
temp = "Default";
(*globalOptions)[Options::ACTIVE_PROFILE.substr(2)].str = temp;
themeOptions = NULL;
profileOptions = NULL;
themeOptions = NULL;
checkProfile();
}
@@ -227,8 +235,9 @@ string GameSettings::profileFile(string filename, string fallback,bool sanity, b
{
char buf[512];
string profile =(*this)[Options::ACTIVE_PROFILE].str;
std::transform(profile.begin(),profile.end(),profile.begin(),::tolower);
if(profile != "" && profile != "Default") {
if(profile != "" && profile != "default") {
//No file, return root of profile directory
if(filename == ""){
sprintf(buf,"%sprofiles/%s",( relative ? "" : RESPATH"/" ),profile.c_str());
@@ -262,13 +271,9 @@ string GameSettings::profileFile(string filename, string fallback,bool sanity, b
return buf;
}
void GameSettings::checkProfile(){
//Load current profile's options. Doesn't save prior set.
//Load current profile's options. Doesn't save prior set.
char buf[512];
SAFE_DELETE(profileOptions);
//Force our directories to exist.
MAKEDIR(RESPATH"/profiles");
@@ -277,14 +282,17 @@ void GameSettings::checkProfile(){
temp+="/stats";
MAKEDIR(temp.c_str());
temp = profileFile(PLAYER_SETTINGS,"",false);
SAFE_DELETE(profileOptions);
profileOptions = NEW GameOptions(temp);
//Force a theme.
temp = (*profileOptions)[Options::ACTIVE_THEME].str;
if(temp == ""){
if((*profileOptions)[Options::ACTIVE_THEME].isDefault()){
temp = "Default";
(*profileOptions)[Options::ACTIVE_THEME].str = "Default";
}else{
temp = (*profileOptions)[Options::ACTIVE_THEME].str;
}
//Load theme options
@@ -295,7 +303,7 @@ void GameSettings::checkProfile(){
}
SAFE_DELETE(themeOptions);
themeOptions = NEW GameOptions(buf);
themeOptions = NEW GameOptions(buf);
//Validation of collection, etc, only happens if the game is up.
if(theGame == NULL || theGame->collection == NULL)
@@ -323,6 +331,7 @@ void GameSettings::checkProfile(){
profileOptions->save();
createUsersFirstDeck(setId);
}
}
void GameSettings::createUsersFirstDeck(int setId){

View File

@@ -149,6 +149,14 @@ void GameStateMenu::Start(){
mMovingW->SetHotSpot(72,16);
JRenderer::GetInstance()->ResetPrivateVRAM();
JRenderer::GetInstance()->EnableVSync(true);
//How many cards total ?
PlayerData * playerdata = NEW PlayerData(mParent->collection);
if(!options[Options::ACTIVE_PROFILE].isDefault())
sprintf(nbcardsStr, "%s: %i of %i cards", options[Options::ACTIVE_PROFILE].str.c_str(), playerdata->collection->totalCards(), mParent->collection->totalCards());
else
sprintf(nbcardsStr, "Database: %i cards", mParent->collection->totalCards());
SAFE_DELETE(playerdata);
}
@@ -221,7 +229,7 @@ void GameStateMenu::fillScroller(){
PlayerData * playerdata = NEW PlayerData(mParent->collection);
sprintf(buff2, _("You currently have %i credits").c_str(),playerdata->credits);
delete playerdata;
SAFE_DELETE(playerdata);
scroller->Add(buff2);
scroller->Add(_("More cards and mods at http://wololo.net/wagic"));
@@ -282,9 +290,6 @@ void GameStateMenu::Update(float dt)
mReadConf = 1;
}
if (!nextDirectory(RESPATH"/sets/","_cards.dat")){
//How many cards total ?
sprintf(nbcardsStr, "Database: %i cards", mParent->collection->totalCards());
//Force default, if necessary.
if(options[Options::ACTIVE_PROFILE].str == "")
options[Options::ACTIVE_PROFILE].str = "Default";
@@ -304,8 +309,16 @@ void GameStateMenu::Update(float dt)
currentState = MENU_STATE_MAJOR_FIRST_TIME | MENU_STATE_MINOR_NONE;
}
}
//List active profile and database size.
PlayerData * playerdata = NEW PlayerData(mParent->collection);
if(!options[Options::ACTIVE_PROFILE].isDefault())
sprintf(nbcardsStr, "%s: %i of %i cards", options[Options::ACTIVE_PROFILE].str.c_str(), playerdata->collection->totalCards(), mParent->collection->totalCards());
else
sprintf(nbcardsStr, "Database: %i cards", mParent->collection->totalCards());
SAFE_DELETE(playerdata);
resetDirectory();
}
}
break;
case MENU_STATE_MAJOR_FIRST_TIME :
options.checkProfile();

View File

@@ -43,11 +43,13 @@ void GameStateOptions::Start()
optionsTabs->Add(optionsList);
optionsList = NEW OptionsList("Profiles");
OptionProfile * pickProf = NEW OptionProfile(mParent);
optionsList->Add(pickProf);
OptionNewProfile * key = NEW OptionNewProfile("","New Profile");
key->bShowValue = false;
optionsList->Add(key);
OptionProfile * pickProf = NEW OptionProfile(mParent);
optionsList->Add(pickProf);
OptionTheme * theme = NEW OptionTheme();
optionsList->Add(theme);
optionsTabs->Add(optionsList);
optionsList = NEW OptionsList("Credits");

View File

@@ -39,6 +39,7 @@ OptionItem::OptionItem( string _id, string _displayValue) {
displayValue = _(_displayValue);
canSelect=true;
hasFocus=false;
bHidden=false;
width = SCREEN_WIDTH;
height = 20;
}
@@ -406,7 +407,7 @@ void OptionsList::Entering(){
//Try to force a selectable option.
if(current == -1){
for (int i = 0 ; i < nbitems; i++){
if(listItems[i]->canSelect) {
if(listItems[i]->Selectable()) {
current = i;
listItems[current]->Entering();
break;
@@ -440,7 +441,7 @@ void OptionsList::Render(){
//Force a selectable option.
if(current == -1){
for (int i = 0 ; i < nbitems; i++){
if(listItems[i]->canSelect) {
if(listItems[i]->Selectable()) {
current = i;
listItems[current]->Entering();
break;
@@ -450,7 +451,7 @@ void OptionsList::Render(){
//Find out how large our list is.
for (int pos=0;pos < nbitems; pos++){
listHeight+=listItems[pos]->height+5;
if(listItems[pos]->canSelect){
if(listItems[pos]->Selectable()){
listSelectable++;
if(pos < current) adjustedCurrent++;
}
@@ -460,14 +461,20 @@ void OptionsList::Render(){
if(listHeight > SCREEN_HEIGHT)
{
width -= 10;
for (start=current;start > 0; start--) {
for (start=current;start > 0; start--){
if(listItems[start]->bHidden)
continue;
vHeight += listItems[start]->height+5;
if(vHeight >= (SCREEN_HEIGHT-60)/2)
break;
}
vHeight = 0;
for (nowPos=nbitems;nowPos > 1; nowPos--)
for (nowPos=nbitems;nowPos > 1; nowPos--){
if(listItems[start]->bHidden)
continue;
vHeight += listItems[nowPos-1]->height+5;
}
if(vHeight <= SCREEN_HEIGHT-40 && nowPos < start)
start = nowPos;
@@ -481,6 +488,9 @@ void OptionsList::Render(){
if(start >= 0)
{
for (int pos=0;pos < nbitems; pos++){
if(listItems[pos]->bHidden)
continue;
if(pos < start){
vHeight += listItems[pos]->height + 5;
continue;
@@ -523,9 +533,9 @@ void OptionsList::Update(float dt){
{
if (potential > 0){
potential--;
while(potential > 0 && listItems[potential]->canSelect == false)
while(potential > 0 && listItems[potential]->Selectable() == false)
potential--;
if(potential < 0 || !listItems[potential]->canSelect)
if(potential < 0 || !listItems[potential]->Selectable())
potential = -1;
else if(listItems[current]->Leaving()){
current = potential;
@@ -537,9 +547,9 @@ void OptionsList::Update(float dt){
{
if (potential < nbitems-1){
potential++;
while(potential < nbitems-1 && listItems[potential]->canSelect == false)
while(potential < nbitems-1 && listItems[potential]->Selectable() == false)
potential++;
if(potential == nbitems || !listItems[potential]->canSelect)
if(potential == nbitems || !listItems[potential]->Selectable())
potential = -1;
else if(potential != current && listItems[current]->Leaving()){
current = potential;
@@ -647,7 +657,7 @@ bool OptionsMenu::isTab(string name){
return true;
return false;
};
}
int OptionsMenu::Submode()
{
@@ -664,8 +674,8 @@ void OptionsMenu::acceptSubmode()
}
void OptionsMenu::reloadValues()
{
if(current > -1 && current < nbitems)
tabs[current]->reloadValues();
for(int i=0;i<nbitems;i++)
tabs[i]->reloadValues();
}
void OptionsMenu::cancelSubmode()
@@ -764,12 +774,13 @@ int OptionNewProfile::Submode(){
}
return OPTIONS_SUBMODE_NORMAL;
}
OptionString::OptionString(string _id, string _displayValue): OptionItem(_id, _displayValue)
{
bShowValue=true;
if(_id != "")
value=options[_id].str;
};
}
ostream& OptionString::toString(ostream& out) const{
return out << "OptionString ::: displayValue : " << displayValue
@@ -778,3 +789,12 @@ return out << "OptionString ::: displayValue : " << displayValue
<< " ; hasFocus : " << hasFocus
<< " ; x,y : " << x << "," << y;
}
OptionTheme::OptionTheme(): OptionDirectory(RESPATH"/themes",Options::ACTIVE_THEME, "Current Theme"){
addSelection("Default");
sort(selections.begin(),selections.end());
initSelections();
hasFocus=false;
if(selections.size() == 1)
bHidden = true;
}

View File

@@ -364,6 +364,22 @@ void ShopItems::ButtonPressed(int controllerId, int controlId){
tempDeck->addRandomCards(3, sets,1,Constants::RARITY_U);
tempDeck->addRandomCards(11, sets,1,Constants::RARITY_C);
//Check for duplicates. Does not guarentee none, just makes them extremely unlikely.
//Code is kind of inefficient, but shouldn't be used often enough to matter.
int loops=0;
for(map<int,int>::iterator it = tempDeck->cards.begin();it!= tempDeck->cards.end() && loops < 15;it++,loops++){
int dupes = it->second - 1;
if(dupes <= 0)
continue;
for(int x=0;x<dupes;x++)
tempDeck->remove(it->first);
int rarity = (int) tempDeck->database->getCardById(it->first)->getRarity();
tempDeck->addRandomCards(dupes,&rarity);
it = tempDeck->cards.begin();
}
playerdata->collection->add(tempDeck);
myCollection->Add(tempDeck);

View File

@@ -179,7 +179,7 @@ unsigned int WResourceManager::nowTime(){
return ++lastTime;
}
void WResourceManager::clearSamples(){
void WResourceManager::ClearSamples(){
map<string,WCachedSample*>::iterator next;
for(map<string,WCachedSample*>::iterator it = sampleCache.begin();it!=sampleCache.end();it=next){
next = it;
@@ -208,7 +208,7 @@ WCachedSample * WResourceManager::getCachedSample(string filename, bool makenew)
csample->sample = JSoundSystem::GetInstance()->LoadSample(sfile.c_str());
//Potential cache overflow- clean the cache
if(!csample->sample && fileExists(sfile.c_str())){
clearSamples();
ClearSamples();
csample->sample = JSoundSystem::GetInstance()->LoadSample(sfile.c_str());
}
}
@@ -450,6 +450,11 @@ JQuad * WResourceManager::RetrieveCard(MTGCard * card, int type, int style){
JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY, float width, float height, string resname, int style){
for(vector<string>::iterator it=mTextureMissing.begin();it!=mTextureMissing.end();it++){
if((*it) == filename)
return NULL;
}
if(resname == "")
resname = filename;
@@ -504,7 +509,8 @@ JQuad * WResourceManager::RetrieveQuad(string filename, float offX, float offY,
return tc->GetQuad(offX,offY,width,height);
}
//Texture doesn't exist, so no quad.
//Texture doesn't exist, so no quad. Record miss.
mTextureMissing.push_back(filename);
return NULL;
}
void WResourceManager::Release(JTexture * tex){
@@ -578,6 +584,13 @@ JTexture * WResourceManager::RetrieveTexture(string filename, int style){
else
tc = getCachedTexture(filename);
}
if(style == RETRIEVE_MANAGE){
for(vector<string>::iterator it = mTextureMissing.begin();it!=mTextureMissing.end();it++){
if((*it) == filename)
return NULL;
}
}
//Perform lock or unlock on entry.
if(style != RETRIEVE_MANAGE && tc){
@@ -598,8 +611,13 @@ JTexture * WResourceManager::RetrieveTexture(string filename, int style){
textureCache.erase(it);
}
//Pop texture into resource manager
CreateTexture(filename);
return GetTexture(filename);
int val = CreateTexture(filename);
if(val == INVALID_ID){
mTextureMissing.push_back(filename);
return NULL;//file not found
}
return GetTexture(val);
}
//Texture exists! Get it.
@@ -863,7 +881,8 @@ int WResourceManager::fileOK(string filename, bool relative){
}
int WResourceManager::CreateTexture(const string &textureName) {
map<string, int>::iterator itr = mTextureMap.find(textureName);
int id = INVALID_ID;
map<string, int>::iterator itr = mTextureMap.find(textureName);
if (itr == mTextureMap.end())
{
@@ -873,14 +892,18 @@ int WResourceManager::CreateTexture(const string &textureName) {
JTexture *tex = JRenderer::GetInstance()->LoadTexture(path.c_str());
if (tex == NULL)
return INVALID_ID;
int id = mTextureList.size();
if (tex != NULL)
{
id = mTextureList.size();
mTextureList.push_back(tex);
mTextureMap[textureName] = id;
}
else
{
return id;
}
return id;
}
else
return itr->second;
@@ -1000,7 +1023,9 @@ void WResourceManager::Refresh(){
vector<JQuad*>::iterator q;
JTexture * oldtex;
mTextureMissing.clear();
ClearMisses();
ClearSamples();
for(it = textureCache.begin();it!=textureCache.end();it++){
if(it->second == NULL)