diff --git a/data/achievements.xml b/data/achievements.xml
index ae27dce55..71bdf7865 100644
--- a/data/achievements.xml
+++ b/data/achievements.xml
@@ -75,8 +75,7 @@
skidding-1race
skidding-1lap -->
-
+
@@ -99,49 +98,38 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/src/achievements/achievement.cpp b/src/achievements/achievement.cpp
index 7aa60397b..3c64e6303 100644
--- a/src/achievements/achievement.cpp
+++ b/src/achievements/achievement.cpp
@@ -35,7 +35,6 @@
Achievement::Achievement(const AchievementInfo * info)
: m_achievement_info(info)
{
- m_id = info->getID();
m_achieved = false;
} // Achievement
@@ -47,43 +46,21 @@ Achievement::~Achievement()
// ----------------------------------------------------------------------------
/** Loads the value from an XML node.
* \param input*/
-void Achievement::load(const XMLNode *node)
+void Achievement::loadProgress(const XMLNode *node)
{
- node->get("id", &m_id );
node->get("achieved", &m_achieved);
-
- for (unsigned int i = 0; i < node->getNumNodes(); i++)
- {
- const XMLNode *n = node->getNode(i);
- std::string key = n->getName();
- int value = 0;
- n->get("value", &value);
- m_progress_map[key] = value;
- }
} // load
// ----------------------------------------------------------------------------
/** Saves the achievement status to a file.
* \param Output stream.
*/
-void Achievement::save(UTFWriter &out)
+void Achievement::saveProgress(UTFWriter &out)
{
- out << " \n";
- return;
- }
-
- out << ">\n";
- std::map::iterator i;
- for (i = m_progress_map.begin(); i != m_progress_map.end(); ++i)
- {
- out << " <" << i->first
- << " value=\"" << i->second << "\"/>\n";
- }
- out << " \n";
+
+ out << "/>\n";
} // save
// ----------------------------------------------------------------------------
@@ -122,24 +99,11 @@ irr::core::stringw Achievement::getProgressAsString() const
if (m_achieved)
return getInfo()->toString() +"/" + getInfo()->toString();
- switch (m_achievement_info->getCheckType())
- {
- case AchievementInfo::AC_ALL_AT_LEAST:
- for (iter = m_progress_map.begin(); iter != m_progress_map.end(); ++iter)
- {
- progress += iter->second;
- }
- break;
- case AchievementInfo::AC_ONE_AT_LEAST:
- for (iter = m_progress_map.begin(); iter != m_progress_map.end(); ++iter)
- {
- if(iter->second>progress) progress = iter->second;
- }
- break;
- default:
- Log::fatal("Achievement", "Missing getProgressAsString for type %d.",
- m_achievement_info->getCheckType());
- }
+ for (iter = m_progress_map.begin(); iter != m_progress_map.end(); ++iter)
+ {
+ progress += iter->second;
+ }
+
return StringUtils::toWString(progress) + "/" + getInfo()->toString();
} // getProgressAsString
@@ -171,24 +135,6 @@ void Achievement::increase(const std::string & key,
check();
} // increase
-// ----------------------------------------------------------------------------
-/** Called at the end of a race to potentially reset values.
- */
-void Achievement::onRaceEnd()
-{
- if(m_achievement_info->needsResetAfterRace())
- 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.
*/
@@ -215,7 +161,7 @@ void Achievement::check()
{
Online::HTTPRequest * request = new Online::HTTPRequest(true);
PlayerManager::setUserDetails(request, "achieving");
- request->addParameter("achievementid", m_id);
+ request->addParameter("achievementid", getID());
request->queue();
}
diff --git a/src/achievements/achievement.hpp b/src/achievements/achievement.hpp
index 5802d963b..8ef354cae 100644
--- a/src/achievements/achievement.hpp
+++ b/src/achievements/achievement.hpp
@@ -20,6 +20,7 @@
#ifndef HEADER_ACHIEVEMENT_HPP
#define HEADER_ACHIEVEMENT_HPP
+#include "achievements/achievement_info.hpp"
#include "utils/types.hpp"
#include
@@ -30,8 +31,9 @@ class UTFWriter;
class XMLNode;
// ============================================================================
-/** This is the base class for any achievement. It allows achievement status
- * to be saved, and detects when an achievement is fulfilled. It provides
+/** This class tracks the progress of an achievement for a player, whose
+ * definition is stored by an associated AchievementInfo. It allows achievement
+ * status to be saved, and detects when an achievement is fulfilled. It provides
* storage for state information by a generic key-value mapping. The values
* are stored as strings, but can be used to store numerical values. E.g.
* you can call increase("key", 10) for an achievement, which will convert
@@ -44,9 +46,6 @@ class AchievementInfo;
class Achievement
{
private:
- /** The id of this achievement. */
- uint32_t m_id;
-
/** True if this achievement has been achieved. */
bool m_achieved;
@@ -62,27 +61,19 @@ public:
Achievement(const AchievementInfo * info);
virtual ~Achievement();
- virtual void load(const XMLNode *node);
- virtual void save(UTFWriter &out);
+ virtual void loadProgress(const XMLNode *node);
+ virtual void saveProgress(UTFWriter &out);
virtual int getValue(const std::string & key);
void increase(const std::string & key, const std::string &goal_key,
int increase = 1);
virtual void reset();
virtual irr::core::stringw getProgressAsString() const;
- void onRaceEnd();
- void onLapEnd();
- // ------------------------------------------------------------------------
- /** Returns the id of this achievement. */
- uint32_t getID() const { return m_id; }
- // ------------------------------------------------------------------------
- /** Returns the AchievementInfo for this achievement. */
+
+ uint32_t getID() const { return m_achievement_info->getID(); }
const AchievementInfo * getInfo() const { return m_achievement_info; }
- // ------------------------------------------------------------------------
- /** Sets this achievement to be fulfilled. */
+
void setAchieved() { m_achieved = true; };
- // ------------------------------------------------------------------------
- /** Returns if this achievement has been fulfilled. */
bool isAchieved() const { return m_achieved; }
// ------------------------------------------------------------------------
const std::map& getProgress() const
diff --git a/src/achievements/achievement_info.cpp b/src/achievements/achievement_info.cpp
index d732abe83..c4e647e69 100644
--- a/src/achievements/achievement_info.cpp
+++ b/src/achievements/achievement_info.cpp
@@ -17,6 +17,7 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#include "achievements/achievement.hpp"
#include "achievements/achievement_info.hpp"
#include "utils/log.hpp"
@@ -29,7 +30,6 @@
*/
AchievementInfo::AchievementInfo(const XMLNode * input)
{
- m_reset_type = NEVER;
m_id = 0;
m_name = "";
m_description = "";
@@ -47,27 +47,6 @@ AchievementInfo::AchievementInfo(const XMLNode * input)
m_description.c_str());
}
- // 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")
- 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;
- else if (s == "one-at-least")
- m_check_type = AC_ONE_AT_LEAST;
- else
- Log::warn("AchievementInfo", "Achievement check type '%s' unknown.",
- s.c_str());
input->get("secret", &m_is_secret);
// Now load the goal nodes
@@ -82,13 +61,6 @@ AchievementInfo::AchievementInfo(const XMLNode * input)
if (m_goal_values.size() != input->getNumNodes())
Log::fatal("AchievementInfo",
"Duplicate keys for the entries of a MapAchievement found.");
-
- if (m_check_type == AC_ONE_AT_LEAST)
- {
- if (m_goal_values.size() != 1)
- Log::fatal("AchievementInfo",
- "A one-at-least achievement must have exactly one goal.");
- }
} // AchievementInfo
// ----------------------------------------------------------------------------
@@ -99,23 +71,13 @@ irr::core::stringw AchievementInfo::toString() const
{
int count = 0;
std::map::const_iterator iter;
- switch (m_check_type)
+
+ // If all values need to be reached, add up all goal values
+ for (iter = m_goal_values.begin(); iter != m_goal_values.end(); iter++)
{
- case AC_ALL_AT_LEAST:
- // If all values need to be reached, add up all goal values
- for (iter = m_goal_values.begin(); iter != m_goal_values.end(); iter++)
- {
- count += iter->second;
- }
- break;
- case AC_ONE_AT_LEAST:
- // Only one goal is defined for a one-at-least
- count = m_goal_values.begin()->second;
- break;
- default:
- Log::fatal("AchievementInfo", "Missing toString for type %d.",
- m_check_type);
+ count += iter->second;
}
+
return StringUtils::toWString(count);
} // toString
@@ -125,34 +87,12 @@ bool AchievementInfo::checkCompletion(Achievement * achievement) const
{
std::map::const_iterator iter;
- switch (m_check_type)
+ for (iter = m_goal_values.begin(); iter != m_goal_values.end(); iter++)
{
- case AC_ALL_AT_LEAST:
- for (iter = m_goal_values.begin(); iter != m_goal_values.end(); iter++)
- {
- if (achievement->getValue(iter->first) < iter->second)
- return false;
- }
- return true;
- case AC_ONE_AT_LEAST:
- {
- // Test all progress values the kart has.
- const std::map &progress = achievement->getProgress();
- for (iter = progress.begin(); iter != progress.end(); iter++)
- {
- // A one-at-least achievement has only one goal, so use it
- if (iter->second >= m_goal_values.begin()->second)
- return true;
- }
- return false;
+ if (achievement->getValue(iter->first) < iter->second)
+ return false;
}
- default:
- Log::fatal("AchievementInfo", "Missing check for type %d.",
- m_check_type);
- } // switch
-
- // Avoid compiler warning
- return false;
+ return true;
}
// ----------------------------------------------------------------------------
int AchievementInfo::getGoalValue(const std::string &key) const
diff --git a/src/achievements/achievement_info.hpp b/src/achievements/achievement_info.hpp
index 05f090384..37a8adb8e 100644
--- a/src/achievements/achievement_info.hpp
+++ b/src/achievements/achievement_info.hpp
@@ -20,7 +20,6 @@
#ifndef HEADER_ACHIEVEMENT_INFO_HPP
#define HEADER_ACHIEVEMENT_INFO_HPP
-#include "achievements/achievement.hpp"
#include "io/xml_node.hpp"
#include "utils/translation.hpp"
#include "utils/types.hpp"
@@ -32,9 +31,10 @@
class Achievement;
-/** This is the base class for storing the definition of an achievement, e.g.
- * title, description (which is common for all achievements), but also how
- * to achieve this achievement.
+/** This class stores an achievement definition from the xml file, including
+ * title, description, but also how to achieve this achievement.
+ * Constrat with the Achievement class, which is a player-specific instance
+ * tracking the progress of the achievement.
* \ingroup achievements
*/
class AchievementInfo
@@ -56,27 +56,6 @@ public:
ACHIEVE_UNSTOPPABLE = 12
};
- /** Achievement check type:
- * ALL_AT_LEAST: All goal values must be reached (or exceeded).
- * ONE_AT_LEAST: At least one current value reaches or exceedes the goal.
- */
- enum AchievementCheckType
- {
- 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. */
uint32_t m_id;
@@ -87,15 +66,9 @@ private:
/** The description of this achievement. */
irr::core::stringw m_description;
- /** Determines how this achievement is checked if it is successful. */
- AchievementCheckType m_check_type;
-
/** The target values needed to be reached. */
std::map m_goal_values;
- /** Determines when the achievement needs to be reset */
- ResetType m_reset_type;
-
/** A secret achievement has its progress not shown. */
bool m_is_secret;
@@ -107,26 +80,10 @@ public:
virtual bool checkCompletion(Achievement * achievement) const;
int getGoalValue(const std::string &key) const;
- // ------------------------------------------------------------------------
- /** Returns the id of this achievement. */
- uint32_t getID() const { return m_id; }
- // ------------------------------------------------------------------------
- /** Returns the description of this achievement. */
+ uint32_t getID() const { return m_id; }
irr::core::stringw getDescription() const { return _(m_description.c_str()); }
- // ------------------------------------------------------------------------
- /** Returns the name of this achievement. */
- irr::core::stringw getName() const { return _LTR(m_name.c_str()); }
- // ------------------------------------------------------------------------
- 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; }
- // ------------------------------------------------------------------------
- /** Returns if this achievement is a secret achievement. */
- bool isSecret() const { return m_is_secret; }
- // ------------------------------------------------------------------------
+ irr::core::stringw getName() const { return _LTR(m_name.c_str()); }
+ bool isSecret() const { return m_is_secret; }
}; // class AchievementInfo
diff --git a/src/achievements/achievements_status.cpp b/src/achievements/achievements_status.cpp
index 8e998f4c8..3123f03ba 100644
--- a/src/achievements/achievements_status.cpp
+++ b/src/achievements/achievements_status.cpp
@@ -99,7 +99,7 @@ void AchievementsStatus::load(const XMLNode * input)
"achievement. Discarding.");
continue;
}
- achievement->load(xml_achievements[i]);
+ achievement->loadProgress(xml_achievements[i]);
} // for i in xml_achievements
// Load achievement data
@@ -193,7 +193,7 @@ void AchievementsStatus::save(UTFWriter &out)
for(i = m_achievements.begin(); i != m_achievements.end(); i++)
{
if (i->second != NULL)
- i->second->save(out);
+ i->second->saveProgress(out);
}
out << " \n";
for(int i=0;i & achieved_ids)
} // sync
/* This function checks over achievements to update their goals
+ * \param type - the data type triggering the update, used to know
+ * to what enum the enum_id refers to.
+ * \param enum_id - the id of the enum identifying the change triggering
+ * the update.
FIXME It is currently hard-coded to specific achievements,
until it can entirely supersedes the previous system and
removes its complications.
FIXME : a data id don't cover some situations, and the function itself ignores it */
-void AchievementsStatus::updateAchievementsProgress(unsigned int achieve_data_id)
+void AchievementsStatus::updateAchievementsProgress(UpdateType type, unsigned int enum_id)
{
Achievement *beyond_luck = PlayerManager::getCurrentAchievementsStatus()->getAchievement(AchievementInfo::ACHIEVE_BEYOND_LUCK);
if (!beyond_luck->isAchieved())
@@ -393,7 +397,7 @@ void AchievementsStatus::increaseDataVar(unsigned int achieve_data_id, int incre
if (m_variables[achieve_data_id].counter > 10000000)
m_variables[achieve_data_id].counter = 10000000;
- updateAchievementsProgress(achieve_data_id);
+ updateAchievementsProgress(UP_ACHIEVEMENT_DATA, achieve_data_id);
}
#ifdef DEBUG
else
@@ -425,13 +429,7 @@ void AchievementsStatus::onRaceEnd(bool aborted)
{
onLapEnd();
- updateAchievementsProgress(0);
-
- //reset all values that need to be reset
- std::map::iterator iter;
- for ( iter = m_achievements.begin(); iter != m_achievements.end(); ++iter ) {
- iter->second->onRaceEnd();
- }
+ updateAchievementsProgress(UP_ACHIEVEMENT_DATA, 0);
m_variables[POWERUP_USED_1RACE].counter = 0;
m_variables[BANANA_1RACE].counter = 0;
@@ -451,13 +449,7 @@ void AchievementsStatus::onRaceEnd(bool aborted)
// ----------------------------------------------------------------------------
void AchievementsStatus::onLapEnd()
{
- updateAchievementsProgress(0);
-
- //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();
- }
+ updateAchievementsProgress(UP_ACHIEVEMENT_DATA, 0);
m_variables[SKIDDING_1LAP].counter = 0;
} // onLapEnd
@@ -510,5 +502,5 @@ void AchievementsStatus::resetKartHits(int num_karts)
void AchievementsStatus::addKartHit(int kart_id)
{
m_kart_hits[kart_id]++;
- updateAchievementsProgress(0);
+ updateAchievementsProgress(UP_KART_HITS, 0);
} // addKartHit
diff --git a/src/achievements/achievements_status.hpp b/src/achievements/achievements_status.hpp
index c9aabbe0c..3241f2da5 100644
--- a/src/achievements/achievements_status.hpp
+++ b/src/achievements/achievements_status.hpp
@@ -178,6 +178,16 @@ private:
// Reset at the beginning of a race
std::vector m_kart_hits;
+ // To avoid updating achievement progress being
+ // too computationally wasteful, we restrain
+ // what is checked on an update
+ enum UpdateType
+ {
+ UP_ACHIEVEMENT_DATA = 0,
+ UP_TRACK_DATA = 1,
+ UP_KART_HITS = 2,
+ };
+
bool m_online;
bool m_valid;
@@ -195,7 +205,7 @@ public :
void save(UTFWriter &out);
void add(Achievement *achievement);
void sync(const std::vector & achieved_ids);
- void updateAchievementsProgress(unsigned int achieve_data_id);
+ void updateAchievementsProgress(UpdateType type, unsigned int enum_id);
void increaseDataVar(unsigned int achieve_data_id, int increase);
void resetDataVar(unsigned int achieve_data_id);
void onRaceEnd(bool aborted=false);
diff --git a/src/items/powerup.cpp b/src/items/powerup.cpp
index 24ce4c9e0..2a2e4dd85 100644
--- a/src/items/powerup.cpp
+++ b/src/items/powerup.cpp
@@ -18,11 +18,9 @@
#include "items/powerup.hpp"
-#include "achievements/achievement_info.hpp"
-#include "config/player_manager.hpp"
-
#include "audio/sfx_base.hpp"
#include "audio/sfx_manager.hpp"
+#include "config/player_manager.hpp"
#include "config/stk_config.hpp"
#include "items/attachment.hpp"
#include "items/item_manager.hpp"
diff --git a/src/modes/world.cpp b/src/modes/world.cpp
index 8f2e0d62b..7f534a78c 100644
--- a/src/modes/world.cpp
+++ b/src/modes/world.cpp
@@ -18,7 +18,6 @@
#include "modes/world.hpp"
-#include "achievements/achievement_info.hpp"
#include "audio/music_manager.hpp"
#include "audio/sfx_base.hpp"
#include "audio/sfx_manager.hpp"
diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp
index fc76d8e27..58c80b2d6 100644
--- a/src/physics/physics.cpp
+++ b/src/physics/physics.cpp
@@ -18,7 +18,6 @@
#include "physics/physics.hpp"
-#include "achievements/achievement_info.hpp"
#include "animations/three_d_animation.hpp"
#include "config/player_manager.hpp"
#include "config/player_profile.hpp"