diff --git a/projects/mtg/include/Credits.h b/projects/mtg/include/Credits.h index 8037901dd..cc947c9f2 100644 --- a/projects/mtg/include/Credits.h +++ b/projects/mtg/include/Credits.h @@ -1,46 +1,46 @@ -#ifndef _CREDITS_H_ -#define _CREDITS_H_ - - -#include -#include -#include -#include -#include "../include/Player.h" -class GameApp; - -using namespace std; - - -class CreditBonus{ -public: - int value; - string text; - CreditBonus(int _value, string _text); - void Render(float x, float y, JLBFont * font); -}; - -class Credits{ -private: - int isDifficultyUnlocked(); - int isMomirUnlocked(); - int isEvilTwinUnlocked(); - int isRandomDeckUnlocked(); - int unlockRandomSet(); -public: - int value; - Player * p1, *p2; - GameApp * app; - int showMsg; - int unlocked; - JQuad * unlockedQuad; - JTexture * unlockedTex; - string unlockedString; - vector bonus; - Credits(); - ~Credits(); - void compute(Player * _p1, Player * _p2, GameApp * _app); - void Render(); -}; - +#ifndef _CREDITS_H_ +#define _CREDITS_H_ + + +#include +#include +#include +#include +#include "../include/Player.h" +class GameApp; + +using namespace std; + + +class CreditBonus{ +public: + int value; + string text; + CreditBonus(int _value, string _text); + void Render(float x, float y, JLBFont * font); +}; + +class Credits{ +private: + int isDifficultyUnlocked(); + int isMomirUnlocked(); + int isEvilTwinUnlocked(); + int isRandomDeckUnlocked(); + int unlockRandomSet(); +public: + int value; + Player * p1, *p2; + GameApp * app; + int showMsg; + int unlocked; + JQuad * unlockedQuad; + JTexture * unlockedTex; + string unlockedString; + vector bonus; + Credits(); + ~Credits(); + void compute(Player * _p1, Player * _p2, GameApp * _app); + void Render(); +}; + #endif \ No newline at end of file diff --git a/projects/mtg/include/GameOptions.h b/projects/mtg/include/GameOptions.h index dc7031e36..d41eff737 100644 --- a/projects/mtg/include/GameOptions.h +++ b/projects/mtg/include/GameOptions.h @@ -14,25 +14,95 @@ using std::string; #define PLAYER_SETTINGS "options.txt" #define PLAYER_COLLECTION "collection.dat" -struct Options { - static const string MUSICVOLUME; - static const string SFXVOLUME; - static const string DIFFICULTY_MODE_UNLOCKED; - static const string MOMIR_MODE_UNLOCKED; - static const string EVILTWIN_MODE_UNLOCKED; - static const string RANDOMDECK_MODE_UNLOCKED; - static const string DIFFICULTY; - static const string CACHESIZE; - static const string PLASMAEFFECT; - static const string INTERRUPT_SECONDS; - static const string INTERRUPTMYSPELLS; - static const string INTERRUPTMYABILITIES; - static const string OSD; - static const string ACTIVE_PROFILE; - static const string ACTIVE_THEME; - static const string ACTIVE_MODE; - static const string CLOSEDHAND; - static const string HANDDIRECTION; +#define INVALID_OPTION -1 + +//Note to self-- provide some form of options initialization. + +class Options { +public: + friend class GameSettings; + enum { + //Values /must/ match ordering in optionNames, or everything loads wrong. + //Profile settings + ACTIVE_THEME, + ACTIVE_MODE, + MUSICVOLUME, + SFXVOLUME, + DIFFICULTY, + PLASMAEFFECT, + OSD, + CLOSEDHAND, + HANDDIRECTION, + INTERRUPT_SECONDS, + //My interrupts + INTERRUPTMYSPELLS, + INTERRUPTMYABILITIES, + //Other interrupts + INTERRUPT_BEFOREBEGIN, + INTERRUPT_UNTAP, + INTERRUPT_UPKEEP, + INTERRUPT_DRAW, + INTERRUPT_FIRSTMAIN, + INTERRUPT_BEGINCOMBAT, + INTERRUPT_ATTACKERS, + INTERRUPT_BLOCKERS, + INTERRUPT_DAMAGE, + INTERRUPT_ENDCOMBAT, + INTERRUPT_SECONDMAIN, + INTERRUPT_ENDTURN, + INTERRUPT_CLEANUP, + INTERRUPT_AFTEREND, + //Global settings + ACTIVE_PROFILE, + DIFFICULTY_MODE_UNLOCKED, + MOMIR_MODE_UNLOCKED, + EVILTWIN_MODE_UNLOCKED, + RANDOMDECK_MODE_UNLOCKED, + CACHESIZE, + //Theme metrics. These will be phased out fairly soon. + THEME_METRICS, //Start of theme metrics. + LOADING_TC = THEME_METRICS, + STATS_TC, + SCROLLER_TC, + SCROLLER_FC, + MAINMENU_TC, + POPUP_MENU_FC, + POPUP_MENU_TC, + POPUP_MENU_TCH, + MSG_FAIL_TC, + OPTION_ITEM_FC, + OPTION_ITEM_TC, + OPTION_ITEM_TCH, + OPTION_HEADER_FC, + OPTION_HEADER_TC, + OPTION_SCROLLBAR_FC, + OPTION_SCROLLBAR_FCH, + OPTION_TAB_FC, + OPTION_TAB_FCH, + OPTION_TAB_TC, + OPTION_TAB_TCH, + OPTION_TEXT_TC, + OPTION_TEXT_FC, + KEY_TC, + KEY_TCH, + KEY_FC, + KEY_FCH, + KEYPAD_FC, + KEYPAD_FCH, + KEYPAD_TC, + + LAST_NAMED, //Any option after this does not look up in optionNames. + SET_UNLOCKS = LAST_NAMED + 1, //For sets. + }; + + static int optionSet(int setID); + static int optionInterrupt(int gamePhase); + + static int getID(string name); + static string getName(int option); + +private: + static const char* optionNames[]; }; struct Metrics { @@ -40,35 +110,37 @@ struct Metrics { //*_FC is fill-color, *_FCH is highlighted fill color //*_B and *_BH are for secondary text/fill colors, if needed //*_X, *_Y, *_W, *_H are x, y, width and height. - static const string LOADING_TC; - static const string STATS_TC; - static const string SCROLLER_TC; - static const string SCROLLER_FC; - static const string MAINMENU_TC; - static const string POPUP_MENU_FC; - static const string POPUP_MENU_TC; - static const string POPUP_MENU_TCH; - static const string MSG_FAIL_TC; - static const string OPTION_ITEM_FC; - static const string OPTION_ITEM_TC; - static const string OPTION_ITEM_TCH; - static const string OPTION_HEADER_FC; - static const string OPTION_HEADER_TC; - static const string OPTION_SCROLLBAR_FC; - static const string OPTION_SCROLLBAR_FCH; - static const string OPTION_TAB_FC; - static const string OPTION_TAB_FCH; - static const string OPTION_TAB_TC; - static const string OPTION_TAB_TCH; - static const string OPTION_TEXT_TC; - static const string OPTION_TEXT_FC; - static const string KEY_TC; - static const string KEY_TCH; - static const string KEY_FC; - static const string KEY_FCH; - static const string KEYPAD_FC; - static const string KEYPAD_FCH; - static const string KEYPAD_TC; + enum { + LOADING_TC = Options::THEME_METRICS, + STATS_TC, + SCROLLER_TC, + SCROLLER_FC, + MAINMENU_TC, + POPUP_MENU_FC, + POPUP_MENU_TC, + POPUP_MENU_TCH, + MSG_FAIL_TC, + OPTION_ITEM_FC, + OPTION_ITEM_TC, + OPTION_ITEM_TCH, + OPTION_HEADER_FC, + OPTION_HEADER_TC, + OPTION_SCROLLBAR_FC, + OPTION_SCROLLBAR_FCH, + OPTION_TAB_FC, + OPTION_TAB_FCH, + OPTION_TAB_TC, + OPTION_TAB_TCH, + OPTION_TEXT_TC, + OPTION_TEXT_FC, + KEY_TC, + KEY_TCH, + KEY_FC, + KEY_FCH, + KEYPAD_FC, + KEYPAD_FCH, + KEYPAD_TC, + }; }; class GameOption { @@ -83,6 +155,12 @@ public: GameOption(int, string); }; +struct EnumDefinition { + int findIndex(int value); + + typedef pair assoc; + vector values; +}; class GameOptions { public: @@ -90,13 +168,20 @@ class GameOptions { int save(); int load(); - static const char * phaseInterrupts[]; - GameOption& operator[](string); + GameOption& operator[](int); GameOptions(string filename); ~GameOptions(); private: - map values; + bool load_option(int id, string input); //Sends an option to the proper reader. + bool read_default(int id, string input); + bool read_enum(int id, string input, EnumDefinition * def); + + bool save_option(std::ofstream * file, int id, string name, GameOption * opt); //Sends an option to the proper writer. + bool write_default(std::ofstream * file, string name, GameOption * opt); + bool write_enum(std::ofstream * file, string name, GameOption * opt, EnumDefinition * def); + + map values; }; class GameSettings{ @@ -124,11 +209,13 @@ public: void checkProfile(); //Confirms that a profile is loaded and contains a collection. void createUsersFirstDeck(int setId); - GameOption& operator[](string); + GameOption& operator[](int); GameOptions* profileOptions; GameOptions* globalOptions; GameOptions* themeOptions; + static GameOption invalid_option; + private: GameApp * theGame; SimplePad * keypad; diff --git a/projects/mtg/include/OptionItem.h b/projects/mtg/include/OptionItem.h index 7a2f3b709..bf6c85a8d 100644 --- a/projects/mtg/include/OptionItem.h +++ b/projects/mtg/include/OptionItem.h @@ -5,6 +5,7 @@ #include #include #include "../include/GameApp.h" +#include "../include/GameOptions.h" using std::string; @@ -21,7 +22,8 @@ using std::string; class OptionItem { public: - string displayValue, id; + string displayValue; + int id; int hasFocus; bool canSelect; bool bHidden; @@ -29,7 +31,7 @@ public: float width, height; virtual ostream& toString(ostream& out)const; - OptionItem( string _id, string _displayValue); + OptionItem( int _id, string _displayValue); virtual ~OptionItem() {}; virtual bool Selectable() {return (canSelect && !bHidden);}; @@ -52,9 +54,9 @@ class OptionInteger:public OptionItem{ string strDefault; //What to call the default value. int maxValue, increment; - OptionInteger(string _id, string _displayValue, int _maxValue = 1, int _increment = 1, int _defV = 0, string _sDef = ""); + OptionInteger(int _id, string _displayValue, int _maxValue = 1, int _increment = 1, int _defV = 0, string _sDef = ""); - virtual void Reload() {if(id != "") value = options[id].number;}; + virtual void Reload() {if(id != INVALID_OPTION) value = options[id].number;}; virtual void Render(); virtual void setData(); virtual void updateValue(){value+=increment; if (value>maxValue) value=0;}; @@ -64,19 +66,19 @@ class OptionInteger:public OptionItem{ class OptionString:public OptionItem{ public: string value; - OptionString(string _id, string _displayValue); + OptionString(int _id, string _displayValue); virtual void Render(); virtual void setData(); virtual void updateValue(); - virtual void Reload() {if(id != "") value = options[id].str;}; + virtual void Reload() {if(id != INVALID_OPTION) value = options[id].str;}; virtual ostream& toString(ostream& out) const; bool bShowValue; }; class OptionNewProfile:public OptionString{ public: - OptionNewProfile(string _id, string _displayValue) : OptionString(_id, _displayValue) {bShowValue=false;}; + OptionNewProfile(string _displayValue) : OptionString(INVALID_OPTION, _displayValue) {bShowValue=false;}; virtual void updateValue(); virtual void Update(float dt); virtual int Submode(); @@ -85,7 +87,7 @@ class OptionNewProfile:public OptionString{ class OptionHeader:public OptionItem{ public: - OptionHeader(string _displayValue): OptionItem("", _displayValue) { canSelect=false;}; + OptionHeader(string _displayValue): OptionItem(INVALID_OPTION, _displayValue) { canSelect=false;}; virtual void Render(); virtual void setData() {}; virtual void updateValue() {}; @@ -93,7 +95,7 @@ class OptionHeader:public OptionItem{ class OptionText:public OptionItem{ public: - OptionText(string _displayValue): OptionItem("", _displayValue) { canSelect=false;}; + OptionText(string _displayValue): OptionItem(INVALID_OPTION, _displayValue) { canSelect=false;}; virtual void Render(); virtual void setData() {}; virtual void updateValue() {}; @@ -105,7 +107,7 @@ class OptionSelect:public OptionItem{ vector selections; virtual void addSelection(string s); - OptionSelect(string _id, string _displayValue): OptionItem(_id, _displayValue) {value = 0;}; + OptionSelect(int _id, string _displayValue): OptionItem(_id, _displayValue) {value = 0;}; virtual void Reload(){initSelections();}; virtual void Render(); virtual void setData(); @@ -118,7 +120,7 @@ class OptionSelect:public OptionItem{ class OptionDirectory:public OptionSelect{ public: virtual void Reload(); - OptionDirectory(string _root, string _id, string _displayValue); + OptionDirectory(string _root, int _id, string _displayValue); private: string root; }; @@ -130,7 +132,7 @@ class OptionTheme:public OptionDirectory{ class OptionVolume: public OptionInteger{ public: - OptionVolume(string _id, string _displayName, bool _bMusic = false); + OptionVolume(int _id, string _displayName, bool _bMusic = false); virtual void updateValue(); private: bool bMusic; @@ -208,27 +210,43 @@ class OptionsMenu class OptionEnum : public OptionItem { protected: - typedef pair assoc; unsigned index; - vector values; public: - OptionEnum(string id, string displayValue) : OptionItem(id, displayValue), index(0) {}; + OptionEnum(int id, string displayValue); virtual void Reload(); virtual void Render(); virtual void setData(); virtual void updateValue(); + //ourDefined is a virtual wrapper for getDefinition() + virtual EnumDefinition * ourDefined() const {return getDefinition();}; + + static EnumDefinition * getDefinition(); virtual ostream& toString(ostream& out) const; }; class OptionClosedHand : public OptionEnum { public: + friend class GameSettings; enum { INVISIBLE = 0, VISIBLE = 1 }; - OptionClosedHand(string id, string displayValue); + OptionClosedHand(int id, string displayValue); + + static EnumDefinition * getDefinition(); + EnumDefinition * ourDefined() const { return getDefinition();}; + +private: + static EnumDefinition * definition; }; class OptionHandDirection : public OptionEnum { public: + friend class GameSettings; enum { VERTICAL = 0, HORIZONTAL = 1}; - OptionHandDirection(string id, string displayValue); + OptionHandDirection(int id, string displayValue); + + static EnumDefinition * getDefinition(); + EnumDefinition * ourDefined() const { return getDefinition();}; + +private: + static EnumDefinition * definition; }; #endif diff --git a/projects/mtg/src/Credits.cpp b/projects/mtg/src/Credits.cpp index d50cc0fe4..6793f79d9 100644 --- a/projects/mtg/src/Credits.cpp +++ b/projects/mtg/src/Credits.cpp @@ -103,10 +103,7 @@ void Credits::compute(Player * _p1, Player * _p2, GameApp * _app){ }else if((unlocked = unlockRandomSet())) { unlockedTex = resources.RetrieveTexture("set_unlocked.png", RETRIEVE_VRAM); unlockedQuad = resources.RetrieveQuad("set_unlocked.png", 2, 2, 396, 96); - char buffer[4096]; - unlockedString = MtgSets::SetsList->values[unlocked -1]; - sprintf(buffer,"unlocked_%s", unlockedString.c_str()); - options[buffer] = GameOption(1); + options[Options::optionSet(unlocked - 1)] = GameOption(1); options.save(); } if (unlocked){ @@ -239,9 +236,9 @@ int Credits::isRandomDeckUnlocked(){ int Credits::unlockRandomSet(){ if (rand() % 2) return 0; int setId = rand() % MtgSets::SetsList->nb_items; - char buffer[4096]; - string s = MtgSets::SetsList->values[setId]; - sprintf(buffer,"unlocked_%s", s.c_str()); - if (1 == options[buffer].number) return 0; - return setId + 1; + + if (1 == options[Options::optionSet(setId)].number) + return 0; + + return setId + 1; //We add 1 here to show success/failure. Be sure to subtract later. } diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 8b15b19cd..0dd0edd34 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -165,13 +165,13 @@ void GameObserver::userRequestNextGamePhase(){ Phase * cPhaseOld = phaseRing->getCurrentPhase(); - if ((cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) || - cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE || - opponent()->isAI() || - options[GameOptions::phaseInterrupts[currentGamePhase]].number) - mLayers->stackLayer()->AddNextGamePhase(); - else - nextGamePhase(); + if ((cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) || + cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE || + opponent()->isAI() || + options[Options::optionInterrupt(currentGamePhase)].number) + mLayers->stackLayer()->AddNextGamePhase(); + else + nextGamePhase(); } diff --git a/projects/mtg/src/GameOptions.cpp b/projects/mtg/src/GameOptions.cpp index 6ac003be6..0aa1a80f8 100644 --- a/projects/mtg/src/GameOptions.cpp +++ b/projects/mtg/src/GameOptions.cpp @@ -2,49 +2,188 @@ #include "../include/utils.h" #include "../include/MTGDeck.h" #include "../include/GameOptions.h" +#include "../include/OptionItem.h" #include #include #include #include #include -const char* GameOptions::phaseInterrupts[] = { - "interrupt ---", - "interrupt Untap", - "interrupt Upkeep", - "interrupt Draw", - "interrupt Main phase 1", - "interrupt Combat begins", - "interrupt Attackers", - "interrupt Blockers", - "interrupt Combat damage", - "interrupt Combat ends", - "interrupt Main phase 2", - "interrupt End of turn", - "interrupt Cleanup", - "interrupt ---" -}; -//Profile options -const string Options::MUSICVOLUME = "musicVolume"; -const string Options::SFXVOLUME = "sfxVolume"; -const string Options::DIFFICULTY = "difficulty"; -const string Options::PLASMAEFFECT = "plasmaEffect"; -const string Options::INTERRUPT_SECONDS = "interruptSeconds"; -const string Options::INTERRUPTMYSPELLS = "interruptMySpells"; -const string Options::INTERRUPTMYABILITIES = "interruptMyAbilities"; -const string Options::OSD = "displayOSD"; -const string Options::ACTIVE_THEME = "Theme"; -const string Options::ACTIVE_MODE = "Mode"; +const char * Options::optionNames[] = { +//Options set on a per-profile basis + "Theme", + "Mode", + "musicVolume", + "sfxVolume", + "difficulty", + "plasmaEffect", + "displayOSD", + "closed_hand", + "hand_direction", + "interruptSeconds", + "interruptMySpells", + "interruptMyAbilities", +//General interrupts + "interruptBeforeBegin", + "interruptUntap", + "interruptUpkeep", + "interruptDraw", + "interruptFirstMain", + "interruptBeginCombat", + "interruptAttackers", + "interruptBlockers", + "interruptDamage", + "interruptEndCombat", + "interruptSecondMain", + "interruptEndTurn", + "interruptCleanup", + "interruptAfterEnd", //Global options -const string Options::ACTIVE_PROFILE = "_gProfile"; -const string Options::DIFFICULTY_MODE_UNLOCKED = "_gprx_handler"; //huhu -const string Options::MOMIR_MODE_UNLOCKED = "_gprx_rimom"; //haha -const string Options::EVILTWIN_MODE_UNLOCKED = "_gprx_eviltwin"; -const string Options::RANDOMDECK_MODE_UNLOCKED = "_gprx_rnddeck"; -const string Options::CACHESIZE = "_gcacheSize"; -const string Options::CLOSEDHAND = "closed_hand"; -const string Options::HANDDIRECTION = "hand_direction"; + "_gProfile", + "_gprx_handler", + "_gprx_rimom", + "_gprx_eviltwin", + "_gprx_rnddeck", + "_gcacheSize", //Theme metrics + "_tLoadingTC", + "_tStatsTC", + "_tScrollerTC", + "_tScrollerFC", + "_tMainMenuTC", + "_tPopupMenuFC", + "_tPopupMenuTC", + "_tPopupMenuTCH", + "_tMsgFailTC", + "_tOptionItemFC", + "_tOptionItemTC", + "_tOptionItemTCH", + "_tOptionHeaderFC", + "_tOptionHeaderTC", + "_tOptionScrollbarFC", + "_tOptionScrollbarFCH", + "_tOptionHeaderFC", + "_tOptionHeaderFCH", + "_tOptionTabTC", + "_tOptionHeaderTCH", + "_tOptionTextTC", + "_tOptionTextFC", + "_tKeyTC", + "_tKeyTCH", + "_tKeyFC", + "_tKeyFCH", + "_tKeypadFC", + "_tKeypadFCH", + "_tKeypadTC" +}; +int Options::getID(string name){ + if(!name.size()) + INVALID_OPTION; + + std::transform(name.begin(),name.end(),name.begin(),::tolower); + + //Is it a named option? + for(int x = 0; x < LAST_NAMED; x++){ + string lower = Options::optionNames[x]; + std::transform(lower.begin(),lower.end(),lower.begin(),::tolower); + + if(lower == name) + return x; + } + + //Is it an unlocked set? + if(MtgSets::SetsList){ + int unlocked = MtgSets::SetsList->find(name); + if(unlocked != -1) + return Options::optionSet(unlocked); + } + + //Failure. + return INVALID_OPTION; +} + +string Options::getName(int option){ + //Invalid options + if(option < 0) + return ""; + + //Standard named options + if(option < LAST_NAMED) + return optionNames[option]; + + //Unlocked sets. + if(MtgSets::SetsList){ + int setID = option - SET_UNLOCKS; + if(setID >= 0 && setID < MtgSets::SetsList->nb_items){ + char buf[512]; + sprintf(buf,"unlocked_%s",MtgSets::SetsList->values[setID].c_str()); + return buf; + } + } + + //Failed. + return ""; +} + +int Options::optionSet(int setID){ + //Sanity check if possible + if(setID < 0 || (MtgSets::SetsList && setID > MtgSets::SetsList->nb_items)) + return INVALID_OPTION; + + return SET_UNLOCKS + setID; +} + +int Options::optionInterrupt(int gamePhase){ + //Huge, nearly illegible switch block spread out to improve readability. + switch(gamePhase){ + case Constants::MTG_PHASE_BEFORE_BEGIN: + return INTERRUPT_BEFOREBEGIN; + + case Constants::MTG_PHASE_UNTAP: + return INTERRUPT_UNTAP; + + case Constants::MTG_PHASE_UPKEEP: + return INTERRUPT_UPKEEP; + + case Constants::MTG_PHASE_DRAW: + return INTERRUPT_DRAW; + + case Constants::MTG_PHASE_FIRSTMAIN: + return INTERRUPT_FIRSTMAIN; + + case Constants::MTG_PHASE_COMBATBEGIN: + return INTERRUPT_BEGINCOMBAT; + + case Constants::MTG_PHASE_COMBATATTACKERS: + return INTERRUPT_ATTACKERS; + + case Constants::MTG_PHASE_COMBATBLOCKERS: + return INTERRUPT_BLOCKERS; + + case Constants::MTG_PHASE_COMBATDAMAGE: + return INTERRUPT_DAMAGE; + + case Constants::MTG_PHASE_COMBATEND: + return INTERRUPT_ENDCOMBAT; + + case Constants::MTG_PHASE_SECONDMAIN: + return INTERRUPT_SECONDMAIN; + + case Constants::MTG_PHASE_ENDOFTURN: + return INTERRUPT_ENDTURN; + + case Constants::MTG_PHASE_CLEANUP: + return INTERRUPT_CLEANUP; + + case Constants::MTG_PHASE_AFTER_EOT: + return INTERRUPT_AFTEREND; + } + + return INVALID_OPTION; +} + +//Theme metrics +/* const string Metrics::LOADING_TC = "_tLoadingTC"; const string Metrics::STATS_TC = "_tStatsTC"; const string Metrics::SCROLLER_TC = "_tScrollerTC"; @@ -73,7 +212,7 @@ const string Metrics::KEY_FC = "_tKeyFC"; const string Metrics::KEY_FCH = "_tKeyFCH"; const string Metrics::KEYPAD_FC = "_tKeypadFC"; const string Metrics::KEYPAD_FCH = "_tKeypadFCH"; -const string Metrics::KEYPAD_TC = "_tKeypadTC"; +const string Metrics::KEYPAD_TC = "_tKeypadTC"; */ GameOption::GameOption(int value) : number(value){} @@ -130,6 +269,59 @@ GameOptions::GameOptions(string filename){ mFilename = filename; load(); } + +bool GameOptions::read_default(int id, string input){ + bool bNumeric = true; + + if(!input.size()){ + values[id] = GameOption(0); + return true; //Default reader doesn't care about invalid formatting. + } + + //Is it a number? + for(size_t x=0;x::iterator it; + for(it=def->values.begin();it != def->values.end();it++){ + if(it->second == input){ + values[id] = GameOption(it->first); + return true; + } + } + + return false; +} +bool GameOptions::load_option(int id, string input){ + switch(id){ + case Options::HANDDIRECTION: + return read_enum(id, input, OptionHandDirection::getDefinition()); + case Options::CLOSEDHAND: + return read_enum(id, input, OptionClosedHand::getDefinition()); + default: + return read_default(id, input); + } + + return false; +} + int GameOptions::load(){ std::ifstream file(mFilename.c_str()); std::string s; @@ -137,47 +329,91 @@ int GameOptions::load(){ if(file){ while(std::getline(file,s)){ int found =s.find("="); - bool bnumber = true; string name = s.substr(0,found); string val = s.substr(found+1); - for(size_t x=0;xstr ==""){ + if(opt->number == 0) //This is absolutely default. No need to write it. + return true; + + //It's a number! + sprintf(writer,"%s=%d\n", name.c_str(), opt->number); + } + else + sprintf(writer,"%s=%s\n", name.c_str(), opt->str.c_str()); + + (*file)<number < 0 || opt->number >= (int) def->values.size()) + return false; + + char writer[1024]; + sprintf(writer,"%s=%s\n", name.c_str(), def->values[opt->number].second.c_str()); + + (*file)<::iterator it; + map::iterator it; for ( it=values.begin() ; it != values.end(); it++ ){ - if(it->second.str ==""){ - sprintf(writer,"%s=%d\n", it->first.c_str(), it->second.number); - if(it->second.number==0) - continue; - } - else - sprintf(writer,"%s=%s\n", it->first.c_str(), it->second.str.c_str()); - file<first); + if(!name.size()) + continue; + + //Save it. + save_option(&file, it->first, name, &it->second); } - file.close(); + file.close(); } return 1; } -GameOption& GameOptions::operator[](string option_name) { - return values[option_name]; +GameOption& GameOptions::operator[](int optionID) { + return values[optionID]; } GameOptions::~GameOptions(){ @@ -206,19 +442,35 @@ GameSettings::~GameSettings(){ SAFE_DELETE(globalOptions); SAFE_DELETE(profileOptions); SAFE_DELETE(themeOptions); + + SAFE_DELETE(OptionHandDirection::definition); + SAFE_DELETE(OptionClosedHand::definition); } -GameOption& GameSettings::operator[](string option_name){ - if(option_name.size() > 2){ - if(option_name[0] == '_' && option_name[1] == 't') - return (*themeOptions)[option_name.substr(2)]; - else if(option_name[0] == '_' && option_name[1] == 'g') - return (*globalOptions)[option_name.substr(2)]; +GameOption GameSettings::invalid_option = GameOption(0); + +GameOption& GameSettings::operator[](int optionID){ + string option_name = Options::getName(optionID); + + //Last chance sanity checking. + if(!option_name.size()){ + OutputDebugString("Error: Accessing invalid option.\n"); + invalid_option.number = 0; + invalid_option.str = ""; + return invalid_option; } - return (*profileOptions)[option_name]; + if(option_name.size() > 2){ + if(option_name[0] == '_' && option_name[1] == 't') + return (*themeOptions)[optionID]; + else if(option_name[0] == '_' && option_name[1] == 'g') + return (*globalOptions)[optionID]; + } + + return (*profileOptions)[optionID]; } + int GameSettings::save(){ if(globalOptions) globalOptions->save(); @@ -308,7 +560,7 @@ void GameSettings::checkProfile(){ if(theGame == NULL || theGame->collection == NULL) return; - string pcFile = profileFile(PLAYER_COLLECTION); + string pcFile = profileFile(PLAYER_COLLECTION,"",false); if(!pcFile.size() || !fileExists(pcFile.c_str())) { //If we had any default settings, we'd set them here. @@ -324,11 +576,21 @@ void GameSettings::checkProfile(){ } } + //Make the proper directories + if(profileOptions){ + //Force our directories to exist. + MAKEDIR(RESPATH"/profiles"); + string temp = profileFile("","",false,false); + MAKEDIR(temp.c_str()); + temp+="/stats"; + MAKEDIR(temp.c_str()); + temp = profileFile(PLAYER_SETTINGS,"",false); + + profileOptions->save(); + } + //Save this set as "unlocked" - char buffer[4096]; - string s = MtgSets::SetsList->values[setId]; - sprintf(buffer,"unlocked_%s", s.c_str()); - (*profileOptions)[buffer]=1; + (*profileOptions)[Options::optionSet(setId)]=1; profileOptions->save(); //Give the player their first deck @@ -411,3 +673,13 @@ string GameSettings::keypadFinish(){ void GameSettings::keypadShutdown(){ SAFE_DELETE(keypad); } + +int EnumDefinition::findIndex(int value){ + vector::iterator it; + for(it = values.begin();it!=values.end();it++){ + if(it->first == value) + return it - values.begin(); + } + + return 0; //Default! +} \ No newline at end of file diff --git a/projects/mtg/src/GameStateMenu.cpp b/projects/mtg/src/GameStateMenu.cpp index dec4d626b..41c66d802 100644 --- a/projects/mtg/src/GameStateMenu.cpp +++ b/projects/mtg/src/GameStateMenu.cpp @@ -188,7 +188,6 @@ void GameStateMenu::fillScroller(){ int totalGames = 0; for (int j=1; j<6; j++){ - sprintf(buffer, "stats/player_deck%i.txt",j); string deckstats = options.profileFile(buffer); if(fileExists(deckstats.c_str())){ @@ -224,9 +223,7 @@ void GameStateMenu::fillScroller(){ //Unlocked sets int nbunlocked = 0; for (int i = 0; i < MtgSets::SetsList->nb_items; i++){ - string s = MtgSets::SetsList->values[i]; - sprintf(buffer,"unlocked_%s", s.c_str()); - if (1 == options[buffer].number) nbunlocked++; + if (1 == options[Options::optionSet(i)].number) nbunlocked++; } sprintf(buff2, _("You have unlocked %i expansions out of %i").c_str(),nbunlocked, MtgSets::SetsList->nb_items); scroller->Add(buff2); diff --git a/projects/mtg/src/GameStateOptions.cpp b/projects/mtg/src/GameStateOptions.cpp index 69e5bd64e..3f3f1607f 100644 --- a/projects/mtg/src/GameStateOptions.cpp +++ b/projects/mtg/src/GameStateOptions.cpp @@ -48,7 +48,7 @@ void GameStateOptions::Start() optionsTabs->Add(optionsList); optionsList = NEW OptionsList("Profiles"); - OptionNewProfile * key = NEW OptionNewProfile("","New Profile"); + OptionNewProfile * key = NEW OptionNewProfile("New Profile"); key->bShowValue = false; optionsList->Add(key); OptionProfile * pickProf = NEW OptionProfile(mParent); diff --git a/projects/mtg/src/GameStateShop.cpp b/projects/mtg/src/GameStateShop.cpp index a0b2e8cbc..fdfeacb51 100644 --- a/projects/mtg/src/GameStateShop.cpp +++ b/projects/mtg/src/GameStateShop.cpp @@ -71,18 +71,14 @@ void GameStateShop::load(){ for (int i = 0; i < MtgSets::SetsList->nb_items; i++){ string s = MtgSets::SetsList->values[i]; if (s.compare("10E") == 0) defaultSet = i; - char buffer[4096]; - sprintf(buffer,"unlocked_%s", s.c_str()); - unlocked[i] = options[buffer].number; + + unlocked[i] = options[Options::optionSet(i)].number; if (unlocked[i]) ok = 1; } if (!ok){ unlocked[defaultSet] = 1; - string s = MtgSets::SetsList->values[defaultSet]; - char buffer[4096]; - sprintf(buffer,"unlocked_%s", s.c_str()); - options[buffer] = GameOption(1); + options[Options::optionSet(defaultSet)] = GameOption(1); options.save(); } diff --git a/projects/mtg/src/OptionItem.cpp b/projects/mtg/src/OptionItem.cpp index e9a66f749..101f1af59 100644 --- a/projects/mtg/src/OptionItem.cpp +++ b/projects/mtg/src/OptionItem.cpp @@ -1,8 +1,6 @@ #include "../include/config.h" #include "../include/OptionItem.h" -#include "../include/GameApp.h" #include -#include "../include/GameOptions.h" #include "../include/PlayerData.h" #include "../include/Translate.h" #include @@ -34,7 +32,7 @@ return out << "OptionItem ::: displayValue : " << displayValue << " ; x,y : " << x << "," << y; } -OptionItem::OptionItem( string _id, string _displayValue) { +OptionItem::OptionItem( int _id, string _displayValue) { id = _id; displayValue = _(_displayValue); canSelect=true; @@ -72,7 +70,7 @@ void OptionInteger::Render(){ mFont->DrawString(buf,width -10 ,y,JGETEXT_RIGHT); } -OptionInteger::OptionInteger(string _id, string _displayValue, int _maxValue, int _increment, int _defV, string _sDef): OptionItem(_id, _displayValue){ +OptionInteger::OptionInteger(int _id, string _displayValue, int _maxValue, int _increment, int _defV, string _sDef): OptionItem(_id, _displayValue){ defValue = _defV; strDefault = _sDef; maxValue = _maxValue; @@ -84,7 +82,7 @@ OptionInteger::OptionInteger(string _id, string _displayValue, int _maxValue, in } void OptionInteger::setData(){ - if(id != "") + if(id != INVALID_OPTION) options[id] = GameOption(value); } @@ -130,7 +128,8 @@ void OptionSelect::Render(){ void OptionSelect::setData() { - if(id == "") return; + if(id == INVALID_OPTION) return; + if (value < selections.size()) options[id] = GameOption(selections[value]); } @@ -356,7 +355,7 @@ void OptionDirectory::Reload(){ initSelections(); } -OptionDirectory::OptionDirectory(string _root, string _id, string _displayValue): OptionSelect(_id, _displayValue){ +OptionDirectory::OptionDirectory(string _root, int _id, string _displayValue): OptionSelect(_id, _displayValue){ DIR *mDip; struct dirent *mDit; char buf[4096]; @@ -741,8 +740,8 @@ void OptionString::Render(){ } void OptionString::setData(){ - if(id != "") - options[id] = GameOption(value); + if(id != INVALID_OPTION) + options[id] = GameOption(value); } void OptionString::updateValue(){ options.keypadStart(value,&value); @@ -780,10 +779,10 @@ int OptionNewProfile::Submode(){ return OPTIONS_SUBMODE_NORMAL; } -OptionString::OptionString(string _id, string _displayValue): OptionItem(_id, _displayValue) +OptionString::OptionString(int _id, string _displayValue): OptionItem(_id, _displayValue) { bShowValue=true; - if(_id != "") + if(id != INVALID_OPTION) value=options[_id].str; } @@ -810,23 +809,31 @@ void OptionVolume::updateValue(){ value=0; } -OptionVolume::OptionVolume(string id, string displayName, bool music): OptionInteger(id, displayName, 100, 10, 0, "Muted") { +OptionVolume::OptionVolume(int id, string displayName, bool music): OptionInteger(id, displayName, 100, 10, 0, "Muted") { bMusic = music; } void OptionEnum::setData() { - options[id] = GameOption(values[index].first, values[index].second); + EnumDefinition * def = ourDefined(); + if(def) + options[id] = GameOption(def->values[index].first); } void OptionEnum::updateValue() { + EnumDefinition * def = ourDefined(); + if(!def) + return; + ++index; - if (index >= values.size()) index = 0; + if (index >= def->values.size()) index = 0; } void OptionEnum::Render() { + EnumDefinition * def = ourDefined(); + JLBFont * mFont = resources.GetJLBFont("f3"); if (hasFocus) mFont->SetColor(options[Metrics::OPTION_ITEM_TCH].asColor(ARGB(255,255,255,0))); @@ -835,34 +842,66 @@ void OptionEnum::Render() JRenderer * renderer = JRenderer::GetInstance(); renderer->FillRoundRect(x-5,y-2,width-x-5,height,2,options[Metrics::OPTION_ITEM_FC].asColor(ARGB(150,50,50,50))); mFont->DrawString(displayValue.c_str(),x,y); - mFont->DrawString(values[index].second.c_str(), width -10, y, JGETEXT_RIGHT); + + if(def) + mFont->DrawString(def->values[index].second.c_str(), width -10, y, JGETEXT_RIGHT); + else + mFont->DrawString("Default", width -10, y, JGETEXT_RIGHT); +} +OptionEnum::OptionEnum(int id, string displayValue) : OptionItem(id, displayValue){ + Reload(); } - void OptionEnum::Reload() { - for (vector::iterator it = values.begin(); it != values.end(); ++it) - if (it->second == options[id].str) - { - index = it - values.begin(); - return; - } - index = 0; + EnumDefinition * def = ourDefined(); + if(def != NULL) + index = def->findIndex(options[id].number); +} + +EnumDefinition * OptionEnum::getDefinition(){ + return NULL; } ostream& OptionEnum::toString(ostream& out) const { - return (out << values[index].second); + EnumDefinition * def = ourDefined(); + + if(!def) + return (out << "OptionEnum ::: INVALID"); + + return (out << "OptionEnum ::: " << def->values[index].second); } -OptionClosedHand::OptionClosedHand(string id, string displayName) : OptionEnum(id, displayName) +EnumDefinition * OptionClosedHand::definition = NULL; + +EnumDefinition * OptionClosedHand::getDefinition(){ + if(!definition){ + definition = NEW EnumDefinition(); + definition->values.push_back(EnumDefinition::assoc(INVISIBLE, "invisible")); + definition->values.push_back(EnumDefinition::assoc(VISIBLE, "visible")); + } + return definition; +} + +OptionClosedHand::OptionClosedHand(int id, string displayName) : OptionEnum(id, displayName) { - values.push_back(assoc(INVISIBLE, "invisible")); - values.push_back(assoc(VISIBLE, "visible")); + getDefinition(); Reload(); }; -OptionHandDirection::OptionHandDirection(string id, string displayName) : OptionEnum(id, displayName) + +EnumDefinition * OptionHandDirection::definition = NULL; + +EnumDefinition * OptionHandDirection::getDefinition(){ + if(!definition){ + definition = NEW EnumDefinition(); + definition->values.push_back(EnumDefinition::assoc(VERTICAL, "vertical")); + definition->values.push_back(EnumDefinition::assoc(HORIZONTAL, "horizontal")); + } + return definition; +} + +OptionHandDirection::OptionHandDirection(int id, string displayName) : OptionEnum(id, displayName) { - values.push_back(assoc(VERTICAL, "vertical")); - values.push_back(assoc(HORIZONTAL, "horizontal")); + getDefinition(); Reload(); };