diff --git a/data/achievements.xml b/data/achievements.xml
index f0d8b526b..edc8c7345 100644
--- a/data/achievements.xml
+++ b/data/achievements.xml
@@ -1,8 +1,8 @@
-
-
+
+
diff --git a/sources.cmake b/sources.cmake
index 1936ba29e..21c71bf08 100644
--- a/sources.cmake
+++ b/sources.cmake
@@ -1,7 +1,9 @@
# Generated by ./update_file_list.sh. Do not edit this file manually.
set(STK_SOURCES
src/achievements/achievement.cpp
+src/achievements/achievement_info.cpp
src/achievements/achievements_manager.cpp
+src/achievements/achievements_slot.cpp
src/addons/addon.cpp
src/addons/addons_manager.cpp
src/addons/inetwork_http.cpp
@@ -296,7 +298,9 @@ src/utils/vec3.cpp
)
set(STK_HEADERS
src/achievements/achievement.hpp
+src/achievements/achievement_info.hpp
src/achievements/achievements_manager.hpp
+src/achievements/achievements_slot.hpp
src/addons/addon.hpp
src/addons/addons_manager.hpp
src/addons/dummy_network_http.hpp
diff --git a/src/achievements/achievement.cpp b/src/achievements/achievement.cpp
index eee4d6a21..e23680e07 100644
--- a/src/achievements/achievement.cpp
+++ b/src/achievements/achievement.cpp
@@ -29,9 +29,9 @@
#include
// ============================================================================
-Achievement::Achievement(const XMLNode * input)
+Achievement::Achievement(AchievementInfo * info)
{
- input->get("id", &m_id);
+ m_id = info->getID();
m_achieved = false;
}
@@ -42,9 +42,12 @@ Achievement::~Achievement()
}
// ============================================================================
-void Achievement::onAchieving()
+void Achievement::check()
{
- if(!m_achieved)
+ if(m_achieved)
+ return;
+
+ if(m_achievement_info->checkCompletion(this))
{
//show achievement
//send to server
@@ -53,38 +56,77 @@ void Achievement::onAchieving()
}
// ============================================================================
-SingleAchievement::SingleAchievement(const XMLNode * input)
- : Achievement(input)
+SingleAchievement::SingleAchievement(AchievementInfo * info)
+ : Achievement(info)
{
}
// ============================================================================
-void SingleAchievement::check()
+void SingleAchievement::load(XMLNode * input)
{
- if(m_achieved)
- return;
- if(m_progress >= m_goal)
- onAchieving();
-}
-
-
-// ============================================================================
-MapAchievement::MapAchievement(const XMLNode * input)
- : Achievement(input)
-{
-}
-
-// ============================================================================
-void MapAchievement::check()
-{
- if(m_achieved)
- return;
-
- ProgressMap::iterator iter;
- for (iter = m_progress_map.begin(); iter != m_progress_map.end(); ++iter)
+ std::string achieved("");
+ input->get("achieved", &achieved);
+ if(achieved == "true")
{
- if (!iter->second)
- return;
+ m_achieved = true;
+ return;
}
- onAchieving();
+ input->get("value", &m_progress);
}
+// ============================================================================
+void SingleAchievement::save(std::ofstream & out)
+{
+ out << "\n";
+} // save
+
+// ============================================================================
+MapAchievement::MapAchievement(AchievementInfo * info)
+ : Achievement(info)
+{
+}
+
+// ============================================================================
+void MapAchievement::load(XMLNode * input)
+{
+ std::string achieved("");
+ input->get("achieved", &achieved);
+ if(achieved == "true")
+ {
+ m_achieved = true;
+ return;
+ }
+ std::vector xml_entries;
+ input->getNodes("entry", xml_entries);
+ for (unsigned int n=0; n < xml_entries.size(); n++)
+ {
+ std::string key("");
+ xml_entries[n]->get("key", &key);
+ int value(0);
+ xml_entries[n]->get("value", &value);
+ m_progress_map[key] = value;
+ }
+}
+
+// ============================================================================
+void MapAchievement::save(std::ofstream & out)
+{
+ out << "\n";
+ std::map::iterator iter;
+ for ( iter = m_progress_map.begin(); iter != m_progress_map.end(); ++iter ) {
+ out << " first.c_str() << "\" value=\"" << StringUtils::toString(iter->second) << "\"/>\n";
+ }
+ out << "\n";
+} // save
+
+// ============================================================================
+
+int MapAchievement::getValue(const std::string & key)
+{
+ if ( m_progress_map.find(key) != m_progress_map.end())
+ return m_progress_map[key];
+ return 0;
+}
+
diff --git a/src/achievements/achievement.hpp b/src/achievements/achievement.hpp
index 41f0cd453..72e57e15d 100644
--- a/src/achievements/achievement.hpp
+++ b/src/achievements/achievement.hpp
@@ -24,6 +24,7 @@
#include
#include
#include "io/xml_node.hpp"
+#include "achievements/achievement_info.hpp"
// ============================================================================
@@ -32,43 +33,58 @@
* \brief
* \ingroup
*/
+class AchievementInfo;
+
class Achievement
{
protected:
- uint32_t m_id;
- bool m_achieved;
- virtual void check() = 0;
- void onAchieving();
+ uint32_t m_id;
+ bool m_achieved;
+ AchievementInfo * m_achievement_info;
+ void check ();
public:
- Achievement (const XMLNode * input);
- virtual ~Achievement ();
- uint32_t getID() const { return m_id; }
+ Achievement (AchievementInfo * info);
+ virtual ~Achievement ();
+ uint32_t getID () const { return m_id; }
+ virtual void load (XMLNode * input) = 0;
+ virtual void save (std::ofstream & out) = 0;
+
+ enum AchievementType
+ {
+ AT_SINGLE,
+ AT_MAP
+ };
+
}; // class Achievement
class SingleAchievement : public Achievement
{
-private:
- virtual void check();
- int m_goal;
+protected:
int m_progress;
public:
- SingleAchievement (const XMLNode * input);
- virtual ~SingleAchievement () {};
-}; // class Achievement
+ SingleAchievement (AchievementInfo * info);
+ virtual ~SingleAchievement () {};
+
+ void load (XMLNode * input);
+ int getValue () const { return m_progress; }
+ void save (std::ofstream & out);
+}; // class SingleAchievement
class MapAchievement : public Achievement
{
-private:
- virtual void check();
- typedef std::map ProgressMap;
- ProgressMap m_progress_map;
+protected:
+ std::map m_progress_map;
public:
- MapAchievement (const XMLNode * input);
- virtual ~MapAchievement () {};
-}; // class Achievement
+ MapAchievement (AchievementInfo * info);
+ virtual ~MapAchievement () {};
+
+ void load (XMLNode * input);
+ int getValue (const std::string & key);
+ void save (std::ofstream & out);
+}; // class MapAchievement
#endif
diff --git a/src/achievements/achievement_info.cpp b/src/achievements/achievement_info.cpp
new file mode 100644
index 000000000..95f6ee253
--- /dev/null
+++ b/src/achievements/achievement_info.cpp
@@ -0,0 +1,87 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 Glenn De Jonghe
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 3
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// 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_info.hpp"
+
+#include "utils/log.hpp"
+#include "utils/translation.hpp"
+#include "io/xml_writer.hpp"
+
+
+#include
+#include
+#include
+
+// ============================================================================
+AchievementInfo::AchievementInfo(const XMLNode * input)
+{
+ input->get("id", &m_id);
+ input->get("title", &m_title);
+ input->get("description", &m_description);
+
+ std::string reset_after_race("");
+ input->get("reset_after_race", &reset_after_race);
+ m_reset_after_race = reset_after_race == "true";
+
+}
+
+// ============================================================================
+SingleAchievementInfo::SingleAchievementInfo(const XMLNode * input)
+ : AchievementInfo(input)
+{
+ input->get("goal", &m_goal_value);
+}
+
+// ============================================================================
+bool SingleAchievementInfo::checkCompletion(Achievement * achievement) const
+{
+ SingleAchievement * single_achievement = (SingleAchievement *) achievement;
+ if(single_achievement->getValue() >= m_goal_value)
+ return true;
+ return false;
+}
+
+// ============================================================================
+MapAchievementInfo::MapAchievementInfo(const XMLNode * input)
+ : AchievementInfo(input)
+{
+ std::vector xml_entries;
+ input->getNodes("entry", xml_entries);
+ for (unsigned int n=0; n < xml_entries.size(); n++)
+ {
+ std::string key("");
+ xml_entries[n]->get("key", &key);
+ int goal(0);
+ xml_entries[n]->get("goal", &goal);
+ m_goal_values[key] = goal;
+ }
+ if(m_goal_values.size() != xml_entries.size())
+ Log::error("MapAchievementInfo","Duplicate keys for the entries of a MapAchievement found.");
+}
+
+// ============================================================================
+bool MapAchievementInfo::checkCompletion(Achievement * achievement) const
+{
+ MapAchievement * map_achievement = (MapAchievement *) achievement;
+ std::map::iterator iter;
+ for ( iter = m_goal_values.begin(); iter != m_goal_values.end(); iter++ ) {
+ if(map_achievement->getValue(iter->first) < iter->second)
+ return false;
+ }
+ return true;
+}
diff --git a/src/achievements/achievement_info.hpp b/src/achievements/achievement_info.hpp
new file mode 100644
index 000000000..7ad522be1
--- /dev/null
+++ b/src/achievements/achievement_info.hpp
@@ -0,0 +1,85 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 Glenn De Jonghe
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 3
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef HEADER_ACHIEVEMENT_INFO_HPP
+#define HEADER_ACHIEVEMENT_INFO_HPP
+
+#include "utils/types.hpp"
+
+#include
+#include
+#include "io/xml_node.hpp"
+#include "achievements/achievement.hpp"
+
+
+// ============================================================================
+
+class Achievement;
+
+/**
+ * \brief
+ * \ingroup
+ */
+class AchievementInfo
+{
+protected:
+ uint32_t m_id;
+ irr::core::stringw m_title;
+ irr::core::stringw m_description;
+ bool m_reset_after_race;
+
+public:
+ AchievementInfo (const XMLNode * input);
+ virtual ~AchievementInfo () {};
+ uint32_t getID () const { return m_id; }
+ irr::core::stringw getDescription () const { return m_description; }
+ virtual Achievement::AchievementType getType () = 0;
+ virtual bool checkCompletion (Achievement * achievement) const = 0;
+}; // class AchievementInfo
+
+class SingleAchievementInfo : public AchievementInfo
+{
+protected:
+ int m_goal_value;
+
+public:
+ SingleAchievementInfo (const XMLNode * input);
+ virtual ~SingleAchievementInfo () {};
+ int getGoalValue () const { return m_goal_value; }
+ virtual bool checkCompletion (Achievement * achievement) const;
+
+ virtual Achievement::AchievementType getType() { return Achievement::AT_SINGLE; };
+}; // class SingleAchievementInfo
+
+class MapAchievementInfo : public AchievementInfo
+{
+protected:
+ std::map m_goal_values;
+
+public:
+ MapAchievementInfo (const XMLNode * input);
+ virtual ~MapAchievementInfo () {};
+ int getGoalValue (const std::string & key) { return m_goal_values[key];}
+ virtual bool checkCompletion (Achievement * achievement) const;
+
+ virtual Achievement::AchievementType getType() { return Achievement::AT_MAP; };
+}; // class MapAchievementInfo
+
+#endif
+
+/*EOF*/
diff --git a/src/achievements/achievements_manager.cpp b/src/achievements/achievements_manager.cpp
index 51264928c..82ff0b368 100644
--- a/src/achievements/achievements_manager.cpp
+++ b/src/achievements/achievements_manager.cpp
@@ -18,11 +18,12 @@
#include "achievements/achievements_manager.hpp"
-#include "achievements/achievement.hpp"
#include "utils/log.hpp"
#include "utils/translation.hpp"
#include "io/file_manager.hpp"
#include "io/xml_writer.hpp"
+#include "config/player.hpp"
+#include "config/user_config.hpp"
#include
#include
@@ -46,7 +47,8 @@ void AchievementsManager::deallocate()
// ============================================================================
AchievementsManager::AchievementsManager()
{
- parse();
+ parseDataFile();
+ parseConfigFile();
}
// ============================================================================
@@ -55,15 +57,110 @@ AchievementsManager::~AchievementsManager()
}
// ============================================================================
-void AchievementsManager::parse()
+void AchievementsManager::parseDataFile()
{
-
+ const std::string file_name = file_manager->getDataFile("achievements.xml");
+ const XMLNode *root = file_manager->createXMLTree(file_name);
+ unsigned int num_nodes = root->getNumNodes();
+ for(unsigned int i = 0; i < num_nodes; i++)
+ {
+ const XMLNode *node = root->getNode(i);
+ std::string type("");
+ node->get("type", &type);
+ AchievementInfo * achievement_info;
+ if(type == "single")
+ {
+ achievement_info = new SingleAchievementInfo(node);
+ }
+ else if(type == "map")
+ {
+ achievement_info = new MapAchievementInfo(node);
+ }
+ else
+ {
+ Log::error("AchievementsManager::parseAchievements","Non-existent achievement type. Skipping - definitely results in unwanted behaviour.");
+ continue;
+ }
+ m_achievements_info.push_back(achievement_info);
+ }
+ if(num_nodes != m_achievements_info.size())
+ Log::error("AchievementsManager::parseAchievements","Multiple achievements with the same id!");
}
+
+
// ============================================================================
-void AchievementsManager::load()
+void AchievementsManager::parseConfigFile()
{
+ const std::string filename=file_manager->getConfigFile("achievements.xml");
+ XMLNode* root = file_manager->createXMLTree(filename);
+ if(!root || root->getName() != "achievements")
+ {
+ Log::info("AchievementsManager", "Achievements file '%s' will be created.",
+ filename.c_str());
+ createSlotsIfNeeded();
+ save();
+
+ if (root) delete root;
+ return;
+ }
+
+ std::vector xml_slots;
+ root->getNodes("slot", xml_slots);
+ for (unsigned int n=0; n < xml_slots.size(); n++)
+ {
+ AchievementsSlot * slot = new AchievementsSlot(xml_slots[n]);
+ if(!slot->isValid())
+ {
+ Log::warn("AchievementsManager", "Found game slot with faulty or missing information. Discarding it.");
+ delete slot;
+ continue;
+ }
+ m_slots.push_back(slot);
+ }
+
+ bool something_changed = createSlotsIfNeeded();
+ if (something_changed) save();
+
+ delete root;
+} // load
+
+
+
+//-----------------------------------------------------------------------------
+/** Creates a slot for players that don't have one yet
+ * \return true if any were created
+ */
+bool AchievementsManager::createSlotsIfNeeded()
+{
+ bool something_changed = false;
+
+ // make sure all players have at least one game slot associated
+ PtrVector& players = UserConfigParams::m_all_players;
+ for (int n=0; nisOnline() && m_slots[i]->getID() == players[n].getUniqueID())
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ if (!exists)
+ {
+ AchievementsSlot* slot = new AchievementsSlot(players[n].getUniqueID(), false);
+ m_slots.push_back(slot);
+ something_changed = true;
+ }
+ }
+
+ return something_changed;
+} // UnlockManager::createSlotsIfNeeded
+
-}
// ============================================================================
void AchievementsManager::save()
{
@@ -84,54 +181,10 @@ void AchievementsManager::save()
for (unsigned int i = 0; i < m_slots.size(); i++)
{
- m_slots[i].save();
+ m_slots[i]->save(achievements_file);
}
achievements_file << "\n\n";
achievements_file.close();
}
-// ============================================================================
-// ============================================================================
-
-void AchievementsManager::AchievementsSlot::parse()
-{
- const std::string file_name = file_manager->getDataFile("achievements.xml");
- const XMLNode *root = file_manager->createXMLTree(file_name);
- unsigned int num_nodes = root->getNumNodes();
- for(unsigned int i = 0; i < num_nodes; i++)
- {
- const XMLNode *node = root->getNode(i);
- std::string type("");
- node->get("type", &type);
- Achievement * achievement;
- if(type == "single")
- {
- achievement = new SingleAchievement(node);
- }
- else if(type == "map")
- {
- achievement = new MapAchievement(node);
- }
- else
- {
- Log::error("AchievementsManager::parseAchievements","Non-existent achievement type. Skipping - definitely results in unwanted behaviour.");
- continue;
- }
- m_achievements[achievement->getID()] = achievement;
- }
- if(num_nodes != m_achievements.size())
- Log::error("AchievementsManager::parseAchievements","Multiple achievements with the same id!");
-} // parseAchievements
-
-// ============================================================================
-void AchievementsManager::AchievementsSlot::load()
-{
-}
-
-
-// ============================================================================
-void AchievementsManager::AchievementsSlot::save()
-{
-
-}
diff --git a/src/achievements/achievements_manager.hpp b/src/achievements/achievements_manager.hpp
index cf25ebb36..12940f400 100644
--- a/src/achievements/achievements_manager.hpp
+++ b/src/achievements/achievements_manager.hpp
@@ -20,7 +20,8 @@
#define HEADER_ACHIEVEMENTS_MANAGER_HPP
#include "utils/types.hpp"
-#include "achievements/achievement.hpp"
+#include "achievements/achievement_info.hpp"
+#include "achievements/achievements_slot.hpp"
#include
@@ -38,29 +39,22 @@
class AchievementsManager
{
private :
-
- class AchievementsSlot
- {
- std::map m_achievements;
- public :
- void parse();
- void load();
- void save();
- };
- std::vector m_slots;
+ std::vector m_slots;
+ std::vector m_achievements_info;
AchievementsManager ();
~AchievementsManager ();
-
-
+ bool createSlotsIfNeeded();
public:
/**Singleton */
static AchievementsManager * get();
static void deallocate();
- void parse();
+ const std::vector & getAllInfo() const { return m_achievements_info;};
+
+ void parseDataFile();
+ void parseConfigFile();
void save();
- void load();
}; // class AchievementsManager
#endif
diff --git a/src/achievements/achievements_slot.cpp b/src/achievements/achievements_slot.cpp
new file mode 100644
index 000000000..577c0e400
--- /dev/null
+++ b/src/achievements/achievements_slot.cpp
@@ -0,0 +1,115 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 Glenn De Jonghe
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 3
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// 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/achievements_slot.hpp"
+
+#include "achievements/achievement_info.hpp"
+#include "achievements/achievements_manager.hpp"
+#include "utils/log.hpp"
+#include "utils/translation.hpp"
+#include "io/xml_writer.hpp"
+
+#include
+#include
+#include
+// ============================================================================
+AchievementsSlot::AchievementsSlot(const XMLNode * input)
+{
+ int fetched_user_id = input->get("user_id", &m_id);
+ std::string online;
+ int fetched_online = input->get("online", &online);
+ if(!fetched_user_id || !fetched_online || !(online == "true" || online == "false"))
+ {
+ m_valid = false;
+ }
+ m_valid = true;
+ m_online = online == "true";
+
+ createFreshSlot();
+
+ std::vector xml_achievements;
+ input->getNodes("achievement", xml_achievements);
+ for( unsigned int i=0; iget("id", &achievement_id);
+ Achievement * achievement = findAchievement(achievement_id);
+ if(achievement == NULL)
+ {
+ Log::warn("AchievementsSlot", "Found saved achievement data for a non-existent achievement. Discarding.");
+ continue;
+ }
+ achievement->load(xml_achievements[i]);
+ }
+}
+
+// ============================================================================
+AchievementsSlot::AchievementsSlot(std::string id, bool online)
+{
+ m_valid = true;
+ m_online = online;
+ m_id = id;
+
+ createFreshSlot();
+}
+
+// ============================================================================
+void AchievementsSlot::createFreshSlot()
+{
+ m_achievements.clear();
+ std::vector all_info = AchievementsManager::get()->getAllInfo();
+ for( unsigned int i=0; i < all_info.size(); i++)
+ {
+ AchievementInfo * info = all_info[i];
+ Achievement::AchievementType achievement_type = info->getType();
+ Achievement * achievement;
+ if(achievement_type == Achievement::AT_SINGLE)
+ {
+ achievement = new SingleAchievement(info);
+ }
+ else if(achievement_type == Achievement::AT_MAP)
+ {
+ achievement = new MapAchievement(info);
+ }
+ m_achievements[achievement->getID()] = achievement;
+ }
+}
+
+// ============================================================================
+void AchievementsSlot::save(std::ofstream & out)
+{
+ out << " \n";
+ std::map::const_iterator i;
+ for(i = m_achievements.begin(); i != m_achievements.end(); i++)
+ {
+ if (i->second != NULL)
+ i->second->save(out);
+ }
+ out << " \n";
+}
+
+// ============================================================================
+Achievement * AchievementsSlot::findAchievement(uint32_t id)
+{
+ if ( m_achievements.find(id) != m_achievements.end())
+ return m_achievements[id];
+ return NULL;
+}
diff --git a/src/achievements/achievements_slot.hpp b/src/achievements/achievements_slot.hpp
new file mode 100644
index 000000000..e5a1b2cc2
--- /dev/null
+++ b/src/achievements/achievements_slot.hpp
@@ -0,0 +1,52 @@
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2013 Glenn De Jonghe
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 3
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef HEADER_ACHIEVEMENTS_SLOT_HPP
+#define HEADER_ACHIEVEMENTS_SLOT_HPP
+
+#include "utils/types.hpp"
+#include "achievements/achievement.hpp"
+
+#include
+#include
+#include "io/xml_node.hpp"
+
+
+class AchievementsSlot
+{
+private:
+ std::map m_achievements;
+ bool m_online;
+ bool m_valid;
+ std::string m_id;
+
+ void createFreshSlot();
+
+public :
+ AchievementsSlot(const XMLNode * input);
+ AchievementsSlot(std::string id, bool online);
+ bool isValid() const { return m_valid;}
+ void save(std::ofstream & out);
+ bool isOnline() const {return m_online;}
+ const std::string & getID() const {return m_id;}
+ Achievement * findAchievement(uint32_t id);
+};
+
+#endif
+
+/*EOF*/
diff --git a/src/challenges/challenge.cpp b/src/challenges/challenge.cpp
index 31fe02036..844e8f981 100644
--- a/src/challenges/challenge.cpp
+++ b/src/challenges/challenge.cpp
@@ -90,17 +90,11 @@ void Challenge::setSolved(RaceManager::Difficulty d)
//-----------------------------------------------------------------------------
-
-const char* boolstr(bool b)
-{
- return (b ? "true" : "false");
-}
-
void Challenge::save(std::ofstream& writer)
{
writer << " <" << m_data->getId().c_str() << ">\n"
- << " \n"
- << " \n"
- << " \n"
+ << " \n"
+ << " \n"
+ << " \n"
<< " " << m_data->getId().c_str() << ">\n";
} // save
diff --git a/src/main.cpp b/src/main.cpp
index 724cb8708..3dc95f53d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -139,6 +139,7 @@
#include
#include "main_loop.hpp"
+#include "achievements/achievements_manager.hpp"
#include "addons/addons_manager.hpp"
#include "addons/inetwork_http.hpp"
#include "addons/news_manager.hpp"
diff --git a/src/utils/string_utils.hpp b/src/utils/string_utils.hpp
index 73a20cd91..d8c11dddc 100644
--- a/src/utils/string_utils.hpp
+++ b/src/utils/string_utils.hpp
@@ -413,6 +413,11 @@ namespace StringUtils
/** Compute a simple hash of a string */
unsigned int simpleHash(const char* input);
+
+ const char* boolstr(bool b)
+ {
+ return (b ? "true" : "false");
+ }
} // namespace StringUtils
#endif