diff --git a/src/challenges/challenge.hpp b/src/challenges/challenge.hpp index 94acd2bf7..d1ce33a6a 100644 --- a/src/challenges/challenge.hpp +++ b/src/challenges/challenge.hpp @@ -39,7 +39,10 @@ class XMLWriter; class ChallengeData; /** - * \brief The state of a challenge for one player + * \brief The state of a challenge for one player. + * Each Challenge has one ChallengeData associcated, which stores + * the actual data about the challenge. + * * \ingroup challenges */ class Challenge : public NoCopy @@ -61,24 +64,46 @@ public: m_state[RaceManager::DIFFICULTY_HARD] = CH_INACTIVE; } virtual ~Challenge() {}; - void load(const XMLNode* config); - void save(std::ofstream& writer); + void load(const XMLNode* config); + void save(std::ofstream& writer); + void setSolved(RaceManager::Difficulty d); // ------------------------------------------------------------------------ - bool isSolved(RaceManager::Difficulty d) const {return m_state[d]==CH_SOLVED; } + /** Returns if this challenge was solved at the specified difficulty. + */ + bool isSolved(RaceManager::Difficulty d) const + { + return m_state[d]==CH_SOLVED; + } // isSolved // ------------------------------------------------------------------------ - bool isSolvedAtAnyDifficulty() const {return m_state[0]==CH_SOLVED || - m_state[1]==CH_SOLVED || - m_state[2]==CH_SOLVED; } + /** Returns true if this challenge was solved at any difficult. + */ + bool isSolvedAtAnyDifficulty() const + { + return m_state[0]==CH_SOLVED || m_state[1]==CH_SOLVED || + m_state[2]==CH_SOLVED; + } // isSolvedAtAnyDifficulty // ------------------------------------------------------------------------ - bool isActive(RaceManager::Difficulty d) const {return m_state[d]==CH_ACTIVE; } + /** True if this challenge is active at the given difficulty. + */ + bool isActive(RaceManager::Difficulty d) const + { + return m_state[d]==CH_ACTIVE; + } // isActive // ------------------------------------------------------------------------ - void setSolved(RaceManager::Difficulty d); + /** Sets this challenge to be active. + */ + void setActive(RaceManager::Difficulty d) + { + m_state[d] = CH_ACTIVE; + } // setActive // ------------------------------------------------------------------------ - void setActive(RaceManager::Difficulty d) {m_state[d] = CH_ACTIVE; } + /** Returns a pointer to the actual Challenge data. + */ + ChallengeData* getData() { return m_data; } // ------------------------------------------------------------------------ - - ChallengeData* getData() { return m_data; } - const ChallengeData* getData() const { return m_data; } -}; + /** Returns a pointer to the actual Challenge data. + */ + const ChallengeData* getData() const { return m_data; } +}; // Challenge #endif diff --git a/src/challenges/challenge_data.cpp b/src/challenges/challenge_data.cpp index b6925fd27..5a218f056 100644 --- a/src/challenges/challenge_data.cpp +++ b/src/challenges/challenge_data.cpp @@ -37,7 +37,7 @@ ChallengeData::ChallengeData(const std::string& filename) #endif { m_filename = filename; - m_major = RaceManager::MAJOR_MODE_SINGLE; + m_mode = CM_SINGLE_RACE; m_minor = RaceManager::MINOR_MODE_NORMAL_RACE; m_num_laps = -1; m_track_id = ""; @@ -92,9 +92,11 @@ ChallengeData::ChallengeData(const std::string& filename) mode_node->get("major", &mode); if(mode=="grandprix") - m_major = RaceManager::MAJOR_MODE_GRAND_PRIX; + m_mode = CM_GRAND_PRIX; else if(mode=="single") - m_major = RaceManager::MAJOR_MODE_SINGLE; + m_mode = CM_SINGLE_RACE; + else if(mode=="any") + m_mode = CM_ANY; else error("major"); @@ -111,12 +113,12 @@ ChallengeData::ChallengeData(const std::string& filename) const XMLNode* track_node = root->getNode("track"); const XMLNode* gp_node = root->getNode("grandprix"); - if (m_major == RaceManager::MAJOR_MODE_SINGLE && track_node == NULL) + if (m_mode == CM_SINGLE_RACE && track_node == NULL) { throw std::runtime_error("Challenge file " + filename + " has no node!"); } - if (m_major == RaceManager::MAJOR_MODE_GRAND_PRIX && gp_node == NULL) + if (m_mode == CM_GRAND_PRIX && gp_node == NULL) { throw std::runtime_error("Challenge file " + filename + " has no node!"); @@ -201,8 +203,8 @@ ChallengeData::ChallengeData(const std::string& filename) int position = -1; if (!requirements_node->get("position", &position) && - (m_minor==RaceManager::MINOR_MODE_FOLLOW_LEADER || - m_major==RaceManager::MAJOR_MODE_GRAND_PRIX)) + (m_minor == RaceManager::MINOR_MODE_FOLLOW_LEADER || + m_mode == CM_GRAND_PRIX)) { error("position"); } @@ -227,16 +229,16 @@ ChallengeData::ChallengeData(const std::string& filename) for(unsigned int i=0; iget("kart", &s)) - getUnlocks(s, ChallengeData::UNLOCK_KART); + if(unlocks[i]->get("kart", &s)) + setUnlocks(s, ChallengeData::UNLOCK_KART); else if(unlocks[i]->get("track", &s)) - getUnlocks(s, ChallengeData::UNLOCK_TRACK); + addUnlockTrackReward(s); else if(unlocks[i]->get("gp", &s)) - getUnlocks(s, ChallengeData::UNLOCK_GP); + setUnlocks(s, ChallengeData::UNLOCK_GP); else if(unlocks[i]->get("mode", &s)) - getUnlocks(s, ChallengeData::UNLOCK_MODE); + setUnlocks(s, ChallengeData::UNLOCK_MODE); else if(unlocks[i]->get("difficulty", &s)) - getUnlocks(s, ChallengeData::UNLOCK_DIFFICULTY); + setUnlocks(s, ChallengeData::UNLOCK_DIFFICULTY); else { fprintf(stderr, "[ChallengeData] unknown unlock entry.\n"); @@ -276,7 +278,7 @@ void ChallengeData::error(const char *id) const */ void ChallengeData::check() const { - if(m_major==RaceManager::MAJOR_MODE_SINGLE) + if(m_mode==CM_SINGLE_RACE) { try { @@ -287,7 +289,7 @@ void ChallengeData::check() const error("track"); } } - else if(m_major==RaceManager::MAJOR_MODE_GRAND_PRIX) + else if(m_mode==CM_GRAND_PRIX) { const GrandPrixData* gp = grand_prix_manager->getGrandPrix(m_gp_id); @@ -304,15 +306,18 @@ void ChallengeData::check() const } // check // ---------------------------------------------------------------------------- - -void ChallengeData::getUnlocks(const std::string &id, REWARD_TYPE reward) +/** Adds all rewards for fulfilling this challenge. + * \param id Name of track or gp or kart or mode or difficulty reward. + * \param reward Type of reward (track, gp, mode, difficulty, kart). + */ +void ChallengeData::setUnlocks(const std::string &id, RewardType reward) { if (id.empty()) return; switch(reward) { - case UNLOCK_TRACK: addUnlockTrackReward(id); - break; + case UNLOCK_TRACK: assert (false); + break; case UNLOCK_GP: addUnlockGPReward(id); break; @@ -346,12 +351,22 @@ void ChallengeData::getUnlocks(const std::string &id, REWARD_TYPE reward) break; } } // switch -} // getUnlocks +} // setUnlocks + // ---------------------------------------------------------------------------- void ChallengeData::setRace(RaceManager::Difficulty d) const { - race_manager->setMajorMode(m_major); - if(m_major==RaceManager::MAJOR_MODE_SINGLE) + if(m_mode==CM_GRAND_PRIX) + race_manager->setMajorMode(RaceManager::MAJOR_MODE_GRAND_PRIX); + else if(m_mode==CM_SINGLE_RACE) + race_manager->setMajorMode(RaceManager::MAJOR_MODE_SINGLE); + else + { + Log::error("challenge_data", "Invalid mode %d in setRace.", m_mode); + assert(false); + } + + if(m_mode==CM_SINGLE_RACE) { race_manager->setMinorMode(m_minor); race_manager->setTrack(m_track_id); @@ -366,7 +381,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const race_manager->setTimeTarget(m_time[d]); } } - else // GP + else if(m_mode==CM_GRAND_PRIX) { race_manager->setMinorMode(m_minor); const GrandPrixData *gp = grand_prix_manager->getGrandPrix(m_gp_id); @@ -393,7 +408,7 @@ bool ChallengeData::isChallengeFulfilled() const { // GP's use the grandPrixFinished() function, // so they can't be fulfilled here. - if(m_major==RaceManager::MAJOR_MODE_GRAND_PRIX) return false; + if(m_mode==CM_GRAND_PRIX) return false; // Single races // ------------ diff --git a/src/challenges/challenge_data.hpp b/src/challenges/challenge_data.hpp index 6106f1dfd..d5a7edbf1 100644 --- a/src/challenges/challenge_data.hpp +++ b/src/challenges/challenge_data.hpp @@ -34,11 +34,16 @@ class ChallengeData { public: - enum REWARD_TYPE {UNLOCK_TRACK, + /** The type of reward you get when fulfilling this challenge. + */ + enum RewardType + { + UNLOCK_TRACK, UNLOCK_GP, UNLOCK_MODE, UNLOCK_KART, - UNLOCK_DIFFICULTY}; + UNLOCK_DIFFICULTY} + ; // ------------------------------------------------------------------------ class UnlockableFeature { @@ -46,15 +51,35 @@ public: std::string m_name; // internal name irr::core::stringw m_user_name; // not all types of feature have one - REWARD_TYPE m_type; + RewardType m_type; const irr::core::stringw getUnlockedMessage() const; }; // UnlockableFeature // ------------------------------------------------------------------------ - + private: - RaceManager::MajorRaceModeType m_major; + /** The various types of challenges that we support, which esp. determine + * when a challenge is tested if it is fulfilled. For now we have GP + * (a GP challenge, tested at the end of a GP), Race (tested at the + * end of a challenge race), and 'any', which is checked at the end of + * each race (maybe even non challenged once). An example for 'any' is + * 'are all challenges unclocked on highest level', which needs to be + * tested after each race (but is itself not a race mode, so it's not + * that you can start this challenge, which differentiates it from + * a race challenge). */ + enum ChallengeModeType + { + CM_GRAND_PRIX, + CM_SINGLE_RACE, + CM_ANY + }; + + /** The challenge mode of this challenge. */ + ChallengeModeType m_mode; + + /** The minor type, used when m_mode is CM_GP or CM_RACE only. */ RaceManager::MinorRaceModeType m_minor; + int m_num_laps; int m_position[RaceManager::DIFFICULTY_COUNT]; int m_num_karts[RaceManager::DIFFICULTY_COUNT]; @@ -68,8 +93,8 @@ private: /** Version number of the challenge. */ int m_version; - void getUnlocks(const std::string &id, - ChallengeData::REWARD_TYPE reward); + void setUnlocks(const std::string &id, + ChallengeData::RewardType reward); void error(const char *id) const; /** Short, internal name for this challenge. */ @@ -98,27 +123,6 @@ public: virtual void check() const; virtual bool isChallengeFulfilled() const; virtual bool isGPFulfilled() const; - /** Returns the version number of this challenge. */ - int getVersion() const { return m_version; } - - - const std::vector& - getFeatures() const { return m_feature; } - - /** Returns the id of the challenge. */ - const std::string &getId() const { return m_id; } - - /** Sets the id of this challenge. */ - void setId(const std::string& s) { m_id = s; } - - const std::string& getTrackId() const { return m_track_id; } - const std::string& getGPId() const { return m_gp_id; } - - int getNumLaps() const { return m_num_laps; } - - /** get number of required trophies to start this challenge */ - int getNumTrophies() const { return m_num_trophies; } - void addUnlockTrackReward(const std::string &track_name); void addUnlockModeReward(const std::string &internal_mode_name, const irr::core::stringw &user_mode_name); @@ -127,20 +131,106 @@ public: const irr::core::stringw &user_name); void addUnlockKartReward(const std::string &internal_name, const irr::core::stringw &user_name); - - - RaceManager::MajorRaceModeType getMajorMode() const { return m_major; } - RaceManager::MinorRaceModeType getMinorMode() const { return m_minor; } - const irr::core::stringw& getChallengeDescription() const { return m_challenge_description; } + // ------------------------------------------------------------------------ + /** Returns the version number of this challenge. */ + int getVersion() const { return m_version; } - int getPosition(RaceManager::Difficulty difficulty) const { return m_position[difficulty]; } - int getNumKarts(RaceManager::Difficulty difficulty) const { return m_num_karts[difficulty]; } - float getTime (RaceManager::Difficulty difficulty) const { return m_time[difficulty]; } - int getEnergy (RaceManager::Difficulty difficulty) const { return m_energy[difficulty]; } + // ------------------------------------------------------------------------ + /** Returns the list of unlockable features for this challenge. + */ + const std::vector& + getFeatures() const { return m_feature; } - std::string getAIKartIdent(RaceManager::Difficulty difficulty) const { return m_ai_kart_ident[difficulty]; } + // ------------------------------------------------------------------------ + /** Returns the id of the challenge. */ + const std::string &getId() const { return m_id; } + + // ------------------------------------------------------------------------ + /** Sets the id of this challenge. */ + void setId(const std::string& s) { m_id = s; } -}; // Ch + // ------------------------------------------------------------------------ + /** Returns the track associated with this challenge. */ + const std::string& getTrackId() const + { + assert(m_mode==CM_SINGLE_RACE); + return m_track_id; + } // getTrackId + + // ------------------------------------------------------------------------ + /** Returns the id of the grand prix associated with this challenge. */ + const std::string& getGPId() const + { + assert(m_mode==CM_GRAND_PRIX); + return m_gp_id; + } // getGPId + + // ------------------------------------------------------------------------ + /** Return number of laps. */ + int getNumLaps() const + { + assert(m_mode==CM_SINGLE_RACE); + return m_num_laps; + } // getNumLaps + + // ------------------------------------------------------------------------ + /** Get number of required trophies to start this challenge */ + int getNumTrophies() const { return m_num_trophies; } + // ------------------------------------------------------------------------ + /** Returns if this challenge is a grand prix. */ + bool isGrandPrix() const { return m_mode == CM_GRAND_PRIX; } + // ------------------------------------------------------------------------ + /** Returns the challenge mode of this challenge. */ + ChallengeModeType getMode() const { return m_mode; } + // ------------------------------------------------------------------------ + /** Returns the minor mode of this challenge. */ + RaceManager::MinorRaceModeType getMinorMode() const { return m_minor; } + // ------------------------------------------------------------------------ + /** Returns the description of this challenge. + */ + const irr::core::stringw& getChallengeDescription() const + { + return m_challenge_description; + } // getChallengeDescription + + // ------------------------------------------------------------------------ + /** Returns the minimum position the player must have in order to win. + */ + int getPosition(RaceManager::Difficulty difficulty) const + { + return m_position[difficulty]; + } // getPosition + + // ------------------------------------------------------------------------ + /** Returns the number of karts to use. + */ + int getNumKarts(RaceManager::Difficulty difficulty) const + { + return m_num_karts[difficulty]; + } // getNumKarts + // ------------------------------------------------------------------------ + /** Returns the maximum time in which the kart must finish. + */ + float getTime(RaceManager::Difficulty difficulty) const + { + return m_time[difficulty]; + } // getTime + // ------------------------------------------------------------------------ + /** Return the energy that a kart must at least have at the end of a race. + */ + int getEnergy(RaceManager::Difficulty difficulty) const + { + return m_energy[difficulty]; + } // getEnergy + // ------------------------------------------------------------------------ + /** Returns the name of the AI to use (used for boss challenge). + */ + const std::string& getAIKartIdent(RaceManager::Difficulty difficulty) const + { + return m_ai_kart_ident[difficulty]; + } + +}; // ChallengeData #endif // HEADER_CHALLENGE_DATA_HPP diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index e39f7f609..4b011273a 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -774,8 +774,7 @@ void Kart::finishedRace(float time) const Challenge *challenge = slot->getCurrentChallenge(); // In case of a GP challenge don't make the end animation depend // on if the challenge is fulfilled - if(challenge && !challenge->getData()->getMajorMode() - ==RaceManager::MAJOR_MODE_GRAND_PRIX) + if(challenge && !challenge->getData()->isGrandPrix()) { if(challenge->getData()->isChallengeFulfilled()) m_kart_model->setAnimation(KartModel::AF_WIN_START); diff --git a/src/states_screens/dialogs/select_challenge.cpp b/src/states_screens/dialogs/select_challenge.cpp index 73628c2b7..c3b15b85b 100644 --- a/src/states_screens/dialogs/select_challenge.cpp +++ b/src/states_screens/dialogs/select_challenge.cpp @@ -123,7 +123,7 @@ SelectChallengeDialog::SelectChallengeDialog(const float percentWidth, medium_label->setText( getLabel(RaceManager::DIFFICULTY_MEDIUM, c->getData()), false ); expert_label->setText( getLabel(RaceManager::DIFFICULTY_HARD, c->getData()), false ); - if (c->getData()->getMajorMode() == RaceManager::MAJOR_MODE_GRAND_PRIX) + if (c->getData()->isGrandPrix()) { const GrandPrixData* gp = grand_prix_manager->getGrandPrix(c->getData()->getGPId()); getWidget("title")->setText( gp->getName(), true ); @@ -135,7 +135,7 @@ SelectChallengeDialog::SelectChallengeDialog(const float percentWidth, } LabelWidget* typeLbl = getWidget("race_type_val"); - if (c->getData()->getGPId().size() > 0) + if (c->getData()->isGrandPrix()) typeLbl->setText(_("Grand Prix"), false ); else typeLbl->setText( RaceManager::getNameOf(c->getData()->getMinorMode()), false ); diff --git a/src/states_screens/race_gui_overworld.cpp b/src/states_screens/race_gui_overworld.cpp index e6ee38d0a..aaebb33da 100644 --- a/src/states_screens/race_gui_overworld.cpp +++ b/src/states_screens/race_gui_overworld.cpp @@ -466,9 +466,10 @@ void RaceGUIOverworld::drawGlobalMiniMap() break; } - if (challenge->getMajorMode() == RaceManager::MAJOR_MODE_GRAND_PRIX) + if (challenge->isGrandPrix()) { - const GrandPrixData* gp = grand_prix_manager->getGrandPrix(challenge->getGPId()); + const GrandPrixData* gp = + grand_prix_manager->getGrandPrix(challenge->getGPId()); if (gp == NULL) { diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 98b87484f..ca6af7e85 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -1062,7 +1062,7 @@ bool Track::loadMainTrack(const XMLNode &root) m_challenges.push_back( OverworldChallenge(xyz, challenge) ); - if (c != NULL && c->getMajorMode() == RaceManager::MAJOR_MODE_GRAND_PRIX) + if (c && c->isGrandPrix()) { }