diff --git a/data/challenges/alltracks.challenge b/data/challenges/alltracks.challenge index b62128592..dd0b0a26c 100644 --- a/data/challenges/alltracks.challenge +++ b/data/challenges/alltracks.challenge @@ -1,6 +1,7 @@ get("solved", &finished); m_state = finished ? CH_SOLVED : CH_INACTIVE; - m_version = 0; - node->get("version", &m_version); if(!finished) loadAdditionalInfo(node); } // load @@ -181,7 +179,8 @@ void Challenge::load(const XMLNode* challengesNode) //----------------------------------------------------------------------------- void Challenge::save(std::ofstream& writer) { - writer << " <" << getId() << " solved=\"" << (isSolved() ? "true" : "false") << "\""; + writer << " <" << getId() << " solved=\"" + << (isSolved() ? "true" : "false") << "\""; if(!isSolved()) saveAdditionalInfo(writer); writer << " />\n"; } // save diff --git a/src/challenges/challenge.hpp b/src/challenges/challenge.hpp index 8b2cebb52..1fd5a5770 100644 --- a/src/challenges/challenge.hpp +++ b/src/challenges/challenge.hpp @@ -69,8 +69,6 @@ private: std::vector m_feature; /** What needs to be done before accessing this challenge. */ std::vector m_prerequisites; - /** Version number of the challenge. */ - int m_version; public: Challenge(const std::string &id, const std::string &name); diff --git a/src/challenges/challenge_data.cpp b/src/challenges/challenge_data.cpp index aa3af6ab9..d0ca7a9a5 100644 --- a/src/challenges/challenge_data.cpp +++ b/src/challenges/challenge_data.cpp @@ -21,6 +21,7 @@ #include #include +#include "challenges/unlock_manager.hpp" #include "karts/kart.hpp" #include "karts/kart_properties_manager.hpp" #include "modes/linear_world.hpp" @@ -47,9 +48,9 @@ ChallengeData::ChallengeData(const std::string& filename) m_track_name = ""; m_gp_id = ""; m_energy = -1; + m_version = 0; XMLNode *root = new XMLNode( filename ); -// if(!root || root->getName()!="challenges") if(!root || root->getName()!="challenge") { delete root; @@ -58,6 +59,19 @@ ChallengeData::ChallengeData(const std::string& filename) throw std::runtime_error(msg.str()); } + std::string s; + if(!root->get("id", &s) ) error("id"); + setId(s); + + root->get("version", &m_version); + // No need to get the rest of the data if this challenge + // is not supported anyway (id is needed for warning message) + if(!unlock_manager->isSupportedVersion(*this)) + { + delete root; + return; + } + std::string mode; root->get("major", &mode); @@ -78,14 +92,10 @@ ChallengeData::ChallengeData(const std::string& filename) else error("minor"); - std::string s; if(!root->get("name", &s) ) error("name"); //std::cout << " // Challenge name = <" << s.c_str() << ">\n"; setName( _(s.c_str()) ); - if(!root->get("id", &s) ) error("id"); - setId(s); - if(!root->get("description", &s) ) error("description"); setChallengeDescription( _(s.c_str()) ); //std::cout << " // Challenge description = <" << s.c_str() << ">\n"; diff --git a/src/challenges/challenge_data.hpp b/src/challenges/challenge_data.hpp index 817133f13..e12233341 100644 --- a/src/challenges/challenge_data.hpp +++ b/src/challenges/challenge_data.hpp @@ -45,6 +45,8 @@ private: std::string m_track_name; int m_energy; std::string m_filename; + /** Version number of the challenge. */ + int m_version; void getUnlocks(const XMLNode *root, const std:: string type, REWARD_TYPE reward); void error(const char *id) const; @@ -62,6 +64,8 @@ public: virtual void check() const; virtual bool raceFinished(); virtual bool grandPrixFinished(); + /** Returns the version number of this challenge. */ + int getVersion() const { return m_version; } }; // ChallengeData #endif // HEADER_CHALLENGE_DATA_HPP diff --git a/src/challenges/unlock_manager.cpp b/src/challenges/unlock_manager.cpp index 323129121..889542743 100644 --- a/src/challenges/unlock_manager.cpp +++ b/src/challenges/unlock_manager.cpp @@ -106,10 +106,10 @@ void UnlockManager::readAllChallengesInDirs(const std::vector* all_ if (f) { fclose(f); - ChallengeData* newChallenge = NULL; + ChallengeData* new_challenge = NULL; try { - newChallenge = new ChallengeData(filename); + new_challenge = new ChallengeData(filename); } catch (std::runtime_error& ex) { @@ -117,7 +117,7 @@ void UnlockManager::readAllChallengesInDirs(const std::vector* all_ << ex.what() << " : challenge will be ignored.\n\n"; continue; } - addChallenge(newChallenge); + addOrFreeChallenge(new_challenge); } // if file } // for file in files @@ -125,37 +125,52 @@ void UnlockManager::readAllChallengesInDirs(const std::vector* all_ } //----------------------------------------------------------------------------- -void UnlockManager::addChallenge(Challenge *c) +/** If a challenge is supported by this binary (i.e. has an appropriate + * challenge version number), add this challenge to the set of all challenges, + * otherwise free the memory for this challenge. + * \param c The challenge that is either stored or freed. + */ +void UnlockManager::addOrFreeChallenge(ChallengeData *c) { - m_all_challenges[c->getId()]=c; -} // addChallenge + if(isSupportedVersion(*c)) + m_all_challenges[c->getId()]=c; + else + { + printf("[challenge] Challenge '%s' is not supported - ignored.\n", + c->getId().c_str()); + delete c; + } +} // addOrFreeChallenge //----------------------------------------------------------------------------- - +/** Reads a challenge from the given filename. The challenge will then either + * be stored, or (if the challenge version is not supported anymore + * \param filename Name of the challenge file to read. + */ void UnlockManager::addChallenge(const std::string& filename) { - ChallengeData* newChallenge = NULL; + ChallengeData* new_challenge = NULL; try { - newChallenge = new ChallengeData(filename); - newChallenge->check(); + new_challenge = new ChallengeData(filename); + new_challenge->check(); } catch (std::runtime_error& ex) { std::cerr << "\n/!\\ An error occurred while loading challenge file '" << filename << "' : " << ex.what() << " : challenge will be ignored.\n\n"; - if (newChallenge != NULL) delete newChallenge; + if (new_challenge != NULL) delete new_challenge; return; } - addChallenge(newChallenge); + addOrFreeChallenge(new_challenge); } // addChallenge //----------------------------------------------------------------------------- -std::vector UnlockManager::getActiveChallenges() +std::vector UnlockManager::getActiveChallenges() { computeActive(); - std::vector all_active; + std::vector all_active; for(AllChallengesType::iterator i =m_all_challenges.begin(); i!=m_all_challenges.end(); i++) { @@ -165,7 +180,7 @@ std::vector UnlockManager::getActiveChallenges() } // getActiveChallenges //----------------------------------------------------------------------------- -const Challenge* UnlockManager::getChallenge(const std::string& id) +const ChallengeData* UnlockManager::getChallenge(const std::string& id) { if(m_all_challenges.find(id)==m_all_challenges.end()) return NULL; return m_all_challenges[id]; @@ -224,10 +239,22 @@ void UnlockManager::save() challenge_file.close(); } // save +//----------------------------------------------------------------------------- void UnlockManager::playLockSound() const { m_locked_sound->play(); -} +} // playLockSound + +//----------------------------------------------------------------------------- +/** Test if the given challenge is supported by this binary. + * \param challenge The challenge to test. + */ +bool UnlockManager::isSupportedVersion(const ChallengeData &challenge) +{ + // Test if challenge version number is in between minimum + // and maximum supported version. + return (challenge.getVersion()>=1 && challenge.getVersion()<=1); +} // isSupportedVersion //----------------------------------------------------------------------------- void UnlockManager::computeActive() @@ -255,7 +282,7 @@ void UnlockManager::computeActive() for(std::vector::iterator pre =pre_req.begin(); pre!=pre_req.end(); pre++) { - const Challenge*p = getChallenge(*pre); + const ChallengeData *p = getChallenge(*pre); if(!p) { fprintf(stderr,"Challenge prerequisite '%s' of '%s' not found - ignored\n", @@ -310,7 +337,7 @@ void UnlockManager::grandPrixFinished() } // grandPrixFinished //----------------------------------------------------------------------------- -void UnlockManager::lockFeature(Challenge* challenge) +void UnlockManager::lockFeature(const ChallengeData *challenge) { const unsigned int amount = (unsigned int)challenge->getFeatures().size(); for(unsigned int n=0; ngetFeatures().size(); for(unsigned int n=0; n UnlockManager::getUnlockedFeatures() +const std::vector UnlockManager::getUnlockedFeatures() { - std::vector out; + std::vector out; for(AllChallengesType::const_iterator i =m_all_challenges.begin(); i!=m_all_challenges.end(); i++) @@ -362,9 +389,9 @@ const std::vector UnlockManager::getUnlockedFeatures() return out; } //----------------------------------------------------------------------------- -const std::vector UnlockManager::getLockedChallenges() +const std::vector UnlockManager::getLockedChallenges() { - std::vector out; + std::vector out; for(AllChallengesType::const_iterator i =m_all_challenges.begin(); i!=m_all_challenges.end(); i++) diff --git a/src/challenges/unlock_manager.hpp b/src/challenges/unlock_manager.hpp index 9ab9b7223..23ca793d1 100644 --- a/src/challenges/unlock_manager.hpp +++ b/src/challenges/unlock_manager.hpp @@ -22,7 +22,7 @@ #include -#include "challenges/challenge.hpp" +#include "challenges/challenge_data.hpp" #include "utils/no_copy.hpp" #include @@ -38,45 +38,46 @@ class UnlockManager : public NoCopy { private: SFXBase *m_locked_sound; - typedef std::map AllChallengesType; + typedef std::map AllChallengesType; AllChallengesType m_all_challenges; std::map m_locked_features; - std::vector m_unlocked_features; + std::vector m_unlocked_features; void computeActive (); void load (); - void unlockFeature (Challenge* c, bool do_save=true); + void unlockFeature (ChallengeData* c, bool do_save=true); void readAllChallengesInDirs(const std::vector* all_dirs); public: UnlockManager (); ~UnlockManager (); - void addChallenge (Challenge *c); + void addOrFreeChallenge(ChallengeData *c); void addChallenge (const std::string& filename); void save (); - std::vector + std::vector getActiveChallenges(); /** Returns the list of recently unlocked features (e.g. call at the end of a race to know if any features were unlocked) */ - const std::vector + const std::vector getRecentlyUnlockedFeatures() {return m_unlocked_features;} /** Clear the list of recently unlocked challenges */ void clearUnlocked () {m_unlocked_features.clear(); } /** Returns a complete list of all solved challenges */ - const std::vector getUnlockedFeatures(); + const std::vector getUnlockedFeatures(); /** Returns the list of currently inaccessible (locked) challenges */ - const std::vector getLockedChallenges(); + const std::vector getLockedChallenges(); - const Challenge *getChallenge (const std::string& id); + const ChallengeData *getChallenge (const std::string& id); void raceFinished (); void grandPrixFinished (); - void lockFeature (Challenge* challenge); + void lockFeature (const ChallengeData *challenge); bool isLocked (const std::string& feature); + bool isSupportedVersion(const ChallengeData &challenge); /** Eye- (or rather ear-) candy. Play a sound when user tries to access a locked area */ void playLockSound() const; diff --git a/src/states_screens/challenges.cpp b/src/states_screens/challenges.cpp index e60c91bc0..17777a63a 100644 --- a/src/states_screens/challenges.cpp +++ b/src/states_screens/challenges.cpp @@ -72,9 +72,9 @@ void ChallengesScreen::init() // Re-build track list everytime (accounts for locking changes, etc.) w->clearItems(); - const std::vector& activeChallenges = unlock_manager->getActiveChallenges(); - const std::vector& solvedChallenges = unlock_manager->getUnlockedFeatures(); - const std::vector& lockedChallenges = unlock_manager->getLockedChallenges(); + const std::vector& activeChallenges = unlock_manager->getActiveChallenges(); + const std::vector& solvedChallenges = unlock_manager->getUnlockedFeatures(); + const std::vector& lockedChallenges = unlock_manager->getLockedChallenges(); const int activeChallengeAmount = activeChallenges.size(); const int solvedChallengeAmount = solvedChallenges.size(); diff --git a/src/states_screens/dialogs/race_over_dialog.cpp b/src/states_screens/dialogs/race_over_dialog.cpp index 73e241798..1c6f787ab 100644 --- a/src/states_screens/dialogs/race_over_dialog.cpp +++ b/src/states_screens/dialogs/race_over_dialog.cpp @@ -476,10 +476,12 @@ GUIEngine::EventPropagation RaceOverDialog::processEvent(const std::string& even } else if (eventSource == "seeunlocked") { - std::vector unlocked = unlock_manager->getRecentlyUnlockedFeatures(); + std::vector unlocked = + unlock_manager->getRecentlyUnlockedFeatures(); unlock_manager->clearUnlocked(); - FeatureUnlockedCutScene* scene = FeatureUnlockedCutScene::getInstance(); + FeatureUnlockedCutScene* scene = + FeatureUnlockedCutScene::getInstance(); /* scene->addUnlockedKart( const_cast(kart_properties_manager->getKart("gnu")), diff --git a/src/states_screens/feature_unlocked.cpp b/src/states_screens/feature_unlocked.cpp index 4a135c451..6cd2d3067 100644 --- a/src/states_screens/feature_unlocked.cpp +++ b/src/states_screens/feature_unlocked.cpp @@ -21,7 +21,7 @@ #include -#include "challenges/challenge.hpp" +#include "challenges/challenge_data.hpp" #include "guiengine/engine.hpp" #include "guiengine/scalable_font.hpp" #include "io/file_manager.hpp" @@ -484,7 +484,7 @@ void FeatureUnlockedCutScene::onUpdate(float dt, // ---------------------------------------------------------------------------- -void FeatureUnlockedCutScene::addUnlockedThings(const std::vector unlocked) +void FeatureUnlockedCutScene::addUnlockedThings(const std::vector unlocked) { for (unsigned int n=0; n unlocked); + void addUnlockedThings(const std::vector unlocked); /** override from base class to handle escape press */ diff --git a/src/states_screens/grand_prix_lose.cpp b/src/states_screens/grand_prix_lose.cpp index 981ef1bf7..fdbbdaf5d 100644 --- a/src/states_screens/grand_prix_lose.cpp +++ b/src/states_screens/grand_prix_lose.cpp @@ -267,10 +267,12 @@ void GrandPrixLose::eventCallback(GUIEngine::Widget* widget, if (unlock_manager->getRecentlyUnlockedFeatures().size() > 0) { - std::vector unlocked = unlock_manager->getRecentlyUnlockedFeatures(); + std::vector unlocked = + unlock_manager->getRecentlyUnlockedFeatures(); unlock_manager->clearUnlocked(); - FeatureUnlockedCutScene* scene = FeatureUnlockedCutScene::getInstance(); + FeatureUnlockedCutScene* scene = + FeatureUnlockedCutScene::getInstance(); assert(unlocked.size() > 0); scene->addUnlockedThings(unlocked); diff --git a/src/states_screens/grand_prix_win.cpp b/src/states_screens/grand_prix_win.cpp index c7ea26357..65bcc54ba 100644 --- a/src/states_screens/grand_prix_win.cpp +++ b/src/states_screens/grand_prix_win.cpp @@ -394,10 +394,12 @@ void GrandPrixWin::eventCallback(GUIEngine::Widget* widget, if (unlock_manager->getRecentlyUnlockedFeatures().size() > 0) { - std::vector unlocked = unlock_manager->getRecentlyUnlockedFeatures(); + std::vector unlocked = + unlock_manager->getRecentlyUnlockedFeatures(); unlock_manager->clearUnlocked(); - FeatureUnlockedCutScene* scene = FeatureUnlockedCutScene::getInstance(); + FeatureUnlockedCutScene* scene = + FeatureUnlockedCutScene::getInstance(); assert(unlocked.size() > 0); scene->addUnlockedThings(unlocked); diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index f8048d71c..a84ad256d 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -130,7 +130,7 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget, { if(name=="top") { - std::vector unlocked = + std::vector unlocked = unlock_manager->getRecentlyUnlockedFeatures(); unlock_manager->clearUnlocked(); FeatureUnlockedCutScene* scene = FeatureUnlockedCutScene::getInstance();