diff --git a/data/achievements.xml b/data/achievements.xml index feb017a98..d7bc2a542 100644 --- a/data/achievements.xml +++ b/data/achievements.xml @@ -1,6 +1,6 @@ - @@ -13,21 +13,20 @@ - - - - - - + \ No newline at end of file diff --git a/src/achievements/achievement.cpp b/src/achievements/achievement.cpp index 8e07dd60b..ff85fc138 100644 --- a/src/achievements/achievement.cpp +++ b/src/achievements/achievement.cpp @@ -179,6 +179,15 @@ void Achievement::onRaceEnd() reset(); } // onRaceEnd +// ---------------------------------------------------------------------------- +/** Called at the end of a lap to potentially reset values. +*/ +void Achievement::onLapEnd() +{ + if (m_achievement_info->needsResetAfterLap()) + reset(); +} // onLapEnd + // ---------------------------------------------------------------------------- /** Checks if this achievement has been achieved. */ diff --git a/src/achievements/achievement.hpp b/src/achievements/achievement.hpp index ec3790aad..9f7239d98 100644 --- a/src/achievements/achievement.hpp +++ b/src/achievements/achievement.hpp @@ -69,7 +69,8 @@ public: virtual void reset(); virtual irr::core::stringw getProgressAsString() const; - void onRaceEnd(); + void onRaceEnd(); + void onLapEnd(); // ------------------------------------------------------------------------ /** Returns the id of this achievement. */ uint32_t getID() const { return m_id; } diff --git a/src/achievements/achievement_info.cpp b/src/achievements/achievement_info.cpp index 98602cd32..f5d93b88c 100644 --- a/src/achievements/achievement_info.cpp +++ b/src/achievements/achievement_info.cpp @@ -31,7 +31,7 @@ */ AchievementInfo::AchievementInfo(const XMLNode * input) { - m_reset_after_race = false; + m_reset_type = NEVER; m_id = 0; m_title = ""; m_description = ""; @@ -47,10 +47,22 @@ AchievementInfo::AchievementInfo(const XMLNode * input) "ID %d title '%s' description '%s'", m_id, m_title.c_str(), m_description.c_str()); } - input->get("reset-after-race", &m_reset_after_race); - m_check_type = AC_ALL_AT_LEAST; + // Load the reset-type std::string s; + input->get("reset-type", &s); + if (s == "race") + m_reset_type = AFTER_RACE; + else if (s == "lap") + m_reset_type = AFTER_LAP; + else if (s == "never") + m_reset_type = NEVER; + else + Log::warn("AchievementInfo", "Achievement check type '%s' unknown.", + s.c_str()); + + // Load check-type + m_check_type = AC_ALL_AT_LEAST; input->get("check-type", &s); if (s == "all-at-least") m_check_type = AC_ALL_AT_LEAST; diff --git a/src/achievements/achievement_info.hpp b/src/achievements/achievement_info.hpp index 5e52989bf..da3ffdf82 100644 --- a/src/achievements/achievement_info.hpp +++ b/src/achievements/achievement_info.hpp @@ -58,6 +58,17 @@ public: AC_ALL_AT_LEAST, AC_ONE_AT_LEAST }; + /** Achievement reset type: + * AFTER_LAP: Achievement needs to be reset after each lap. + * AFTER_RACE: Achievement needs to be reset after each race. + * NEVER: Achievement does not need to be reset + */ + enum ResetType + { + AFTER_LAP = 1, + AFTER_RACE = 2, + NEVER = 3 + }; private: /** The id of this Achievement. */ @@ -75,8 +86,8 @@ private: /** The target values needed to be reached. */ std::map m_goal_values; - /** True if the achievement needs to be reset after each race. */ - bool m_reset_after_race; + /** Determines when the achievement needs to be reset */ + ResetType m_reset_type; public: AchievementInfo(const XMLNode * input); @@ -96,7 +107,9 @@ public: /** Returns the title of this achievement. */ irr::core::stringw getTitle() const { return m_title; } // ------------------------------------------------------------------------ - bool needsResetAfterRace() const { return m_reset_after_race; } + bool needsResetAfterRace() const { return m_reset_type == AFTER_RACE; } + // ------------------------------------------------------------------------ + bool needsResetAfterLap() const { return m_reset_type == AFTER_LAP; } // ------------------------------------------------------------------------ /** Returns the check type for this achievement. */ AchievementCheckType getCheckType() const { return m_check_type; } diff --git a/src/achievements/achievements_manager.cpp b/src/achievements/achievements_manager.cpp index e13af174e..ec59095cf 100644 --- a/src/achievements/achievements_manager.cpp +++ b/src/achievements/achievements_manager.cpp @@ -95,14 +95,6 @@ AchievementsStatus* return status; } // createAchievementStatus -// ---------------------------------------------------------------------------- -void AchievementsManager::onRaceEnd() -{ - //reset all values that need to be reset - PlayerManager::get()->getCurrentPlayer() - ->getAchievementsStatus()->onRaceEnd(); -} // onRaceEnd - // ---------------------------------------------------------------------------- AchievementInfo * AchievementsManager::getAchievementInfo(uint32_t id) const { diff --git a/src/achievements/achievements_manager.hpp b/src/achievements/achievements_manager.hpp index 67cebf888..d138cb151 100644 --- a/src/achievements/achievements_manager.hpp +++ b/src/achievements/achievements_manager.hpp @@ -71,7 +71,6 @@ public: } // destroy // ======================================================================== - void onRaceEnd(); AchievementInfo* getAchievementInfo(uint32_t id) const; AchievementsStatus* createAchievementsStatus(const XMLNode *node=NULL); // ------------------------------------------------------------------------ diff --git a/src/achievements/achievements_status.cpp b/src/achievements/achievements_status.cpp index 40aa3d34d..74bf54724 100644 --- a/src/achievements/achievements_status.cpp +++ b/src/achievements/achievements_status.cpp @@ -132,3 +132,12 @@ void AchievementsStatus::onRaceEnd() iter->second->onRaceEnd(); } } // onRaceEnd + +void AchievementsStatus::onLapEnd() +{ + //reset all values that need to be reset + std::map::iterator iter; + for (iter = m_achievements.begin(); iter != m_achievements.end(); ++iter) { + iter->second->onLapEnd(); + } +} // onRaceEnd \ No newline at end of file diff --git a/src/achievements/achievements_status.hpp b/src/achievements/achievements_status.hpp index e956dd99b..7aa8edefa 100644 --- a/src/achievements/achievements_status.hpp +++ b/src/achievements/achievements_status.hpp @@ -60,6 +60,7 @@ public : void add(Achievement *achievement); void sync(const std::vector & achieved_ids); void onRaceEnd(); + void onLapEnd(); // ------------------------------------------------------------------------ const std::map& getAllAchievements() { diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index 865e995be..43334bde7 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -17,6 +17,8 @@ #include "modes/linear_world.hpp" +#include "achievements/achievements_manager.hpp" +#include "config/player_manager.hpp" #include "audio/music_manager.hpp" #include "audio/sfx_base.hpp" #include "audio/sfx_manager.hpp" @@ -236,6 +238,14 @@ void LinearWorld::newLap(unsigned int kart_index) KartInfo &kart_info = m_kart_info[kart_index]; AbstractKart *kart = m_karts[kart_index]; + // Reset reset-after-lap achievements + StateManager::ActivePlayer *c = kart->getController()->getPlayer(); + PlayerProfile *p = PlayerManager::get()->getCurrentPlayer(); + if (c && c->getConstProfile() == p) + { + PlayerManager::get()->getCurrentPlayer()->getAchievementsStatus()->onLapEnd(); + } + // Only update the kart controller if a kart that has already finished // the race crosses the start line again. This avoids 'fastest lap' // messages if the end controller does a fastest lap, but especially