cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000   1) //
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000   2) //  SuperTuxKart - a fun racing game with go-kart
18bafc9a (hiker        2015-03-30 11:31:42 +1100   3) //  Copyright (C) 2013-2015 Glenn De Jonghe
18bafc9a (hiker        2015-03-30 11:31:42 +1100   4) //            (C) 2014-2015 Joerg Henrichs
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000   5) //
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000   6) //  This program is free software; you can redistribute it and/or
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000   7) //  modify it under the terms of the GNU General Public License
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000   8) //  as published by the Free Software Foundation; either version 3
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000   9) //  of the License, or (at your option) any later version.
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  10) //
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  11) //  This program is distributed in the hope that it will be useful,
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  12) //  but WITHOUT ANY WARRANTY; without even the implied warranty of
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  13) //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  14) //  GNU General Public License for more details.
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  15) //
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  16) //  You should have received a copy of the GNU General Public License
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  17) //  along with this program; if not, write to the Free Software
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  18) //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  19) 
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  20) 
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  21) #include "achievements/achievement.hpp"
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  22) 
991662fc (hikerstk     2013-09-02 23:02:15 +0000  23) #include "achievements/achievement_info.hpp"
6231e618 (hiker        2014-06-23 09:13:44 +1000  24) #include "guiengine/message_queue.hpp"
a3a5d5fc (hiker        2014-02-20 22:04:03 +1100  25) #include "io/utf_writer.hpp"
502987d3 (hiker        2014-04-10 16:32:58 +1000  26) #include "config/player_manager.hpp"
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  27) #include "utils/log.hpp"
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  28) #include "utils/translation.hpp"
e21ef8d4 (unitraxx     2013-09-01 21:11:15 +0000  29) 
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  30) #include <stdlib.h>
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  31) 
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  32) /** Constructur, initialises this object with the data from the
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  33)  *  corresponding AchievementInfo.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  34)  */
d6f63838 (unitraxx     2013-09-05 02:41:08 +0000  35) Achievement::Achievement(const AchievementInfo * info)
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  36)            : m_achievement_info(info)
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  37) {
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  38)     m_id       = info->getID();
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  39)     m_achieved = false;
b214799a (hiker        2014-02-21 22:15:36 +1100  40) }   // Achievement
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  41) 
b214799a (hiker        2014-02-21 22:15:36 +1100  42) // ----------------------------------------------------------------------------
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  43) Achievement::~Achievement()
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  44) {
b214799a (hiker        2014-02-21 22:15:36 +1100  45) }   // ~Achievement
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  46) 
b214799a (hiker        2014-02-21 22:15:36 +1100  47) // ----------------------------------------------------------------------------
b214799a (hiker        2014-02-21 22:15:36 +1100  48) /** Loads the value from an XML node.
b214799a (hiker        2014-02-21 22:15:36 +1100  49)  *  \param input*/
b214799a (hiker        2014-02-21 22:15:36 +1100  50) void Achievement::load(const XMLNode *node)
b214799a (hiker        2014-02-21 22:15:36 +1100  51) {
b214799a (hiker        2014-02-21 22:15:36 +1100  52)     node->get("id",       &m_id      );
b214799a (hiker        2014-02-21 22:15:36 +1100  53)     node->get("achieved", &m_achieved);
178fc861 (unitraxx     2013-09-04 01:57:04 +0000  54) 
b214799a (hiker        2014-02-21 22:15:36 +1100  55)     for (unsigned int i = 0; i < node->getNumNodes(); i++)
91e77a14 (unitraxx     2013-09-02 20:53:55 +0000  56)     {
b214799a (hiker        2014-02-21 22:15:36 +1100  57)         const XMLNode *n = node->getNode(i);
b214799a (hiker        2014-02-21 22:15:36 +1100  58)         std::string key = n->getName();
b214799a (hiker        2014-02-21 22:15:36 +1100  59)         int value = 0;
b214799a (hiker        2014-02-21 22:15:36 +1100  60)         n->get("value", &value);
91e77a14 (unitraxx     2013-09-02 20:53:55 +0000  61)         m_progress_map[key] = value;
91e77a14 (unitraxx     2013-09-02 20:53:55 +0000  62)     }
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  63) }   // load
91e77a14 (unitraxx     2013-09-02 20:53:55 +0000  64) 
b214799a (hiker        2014-02-21 22:15:36 +1100  65) // ----------------------------------------------------------------------------
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  66) /** Saves the achievement status to a file.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  67)  *  \param Output stream.
b214799a (hiker        2014-02-21 22:15:36 +1100  68)  */
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  69) void Achievement::save(UTFWriter &out)
91e77a14 (unitraxx     2013-09-02 20:53:55 +0000  70) {
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  71)     out << L"        <achievement id=\"" << m_id << L"\" "
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  72)         << L"achieved=\"" << m_achieved << "\"";
b214799a (hiker        2014-02-21 22:15:36 +1100  73)     if (isAchieved())
b214799a (hiker        2014-02-21 22:15:36 +1100  74)     {
b214799a (hiker        2014-02-21 22:15:36 +1100  75)         out << "/>\n";
b214799a (hiker        2014-02-21 22:15:36 +1100  76)         return;
b214799a (hiker        2014-02-21 22:15:36 +1100  77)     }
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  78) 
b214799a (hiker        2014-02-21 22:15:36 +1100  79)     out << ">\n";
b214799a (hiker        2014-02-21 22:15:36 +1100  80)     std::map<std::string, int>::iterator i;
b214799a (hiker        2014-02-21 22:15:36 +1100  81)     for (i = m_progress_map.begin(); i != m_progress_map.end(); ++i)
74ec8980 (unitraxx     2013-09-06 17:56:05 +0000  82)     {
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  83)         out << "          <" << i->first
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  84)             << " value=\"" << i->second << "\"/>\n";
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  85)     }
c67c5a6f (unitraxx     2013-09-05 23:20:39 +0000  86)     out << "        </achievement>\n";
91e77a14 (unitraxx     2013-09-02 20:53:55 +0000  87) }   // save
91e77a14 (unitraxx     2013-09-02 20:53:55 +0000  88) 
b214799a (hiker        2014-02-21 22:15:36 +1100  89) // ----------------------------------------------------------------------------
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  90) /** Returns the value for a key.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  91)  */
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  92) int Achievement::getValue(const std::string & key)
91e77a14 (unitraxx     2013-09-02 20:53:55 +0000  93) {
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  94)     if (m_progress_map.find(key) != m_progress_map.end())
91e77a14 (unitraxx     2013-09-02 20:53:55 +0000  95)         return m_progress_map[key];
91e77a14 (unitraxx     2013-09-02 20:53:55 +0000  96)     return 0;
cd7e9864 (unitraxx     2013-08-30 22:28:57 +0000  97) }
b214799a (hiker        2014-02-21 22:15:36 +1100  98) // ----------------------------------------------------------------------------
5fc300d7 (hiker        2014-02-24 08:21:15 +1100  99) /** Resets all currently key values to 0. Called if the reset-after-race flag
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 100)  *  is set for the corresponding AchievementInfo.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 101)  */
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 102) void Achievement::reset()
178fc861 (unitraxx     2013-09-04 01:57:04 +0000 103) {
178fc861 (unitraxx     2013-09-04 01:57:04 +0000 104)     std::map<std::string, int>::iterator iter;
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 105)     for (iter = m_progress_map.begin(); iter != m_progress_map.end(); ++iter)
9ee06a5f (hikerstk     2014-01-14 11:47:25 +0000 106)     {
178fc861 (unitraxx     2013-09-04 01:57:04 +0000 107)         iter->second = 0;
178fc861 (unitraxx     2013-09-04 01:57:04 +0000 108)     }
178fc861 (unitraxx     2013-09-04 01:57:04 +0000 109) }   // reset
178fc861 (unitraxx     2013-09-04 01:57:04 +0000 110) 
b214799a (hiker        2014-02-21 22:15:36 +1100 111) // ----------------------------------------------------------------------------
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 112) /** Returns how much of an achievement has been achieved in the form n/m.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 113)  *  The AchievementInfo adds up all goal values to get 'm', and this
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 114)  *  this class end up all current key values for 'n'.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 115)  */
642797bd (hiker        2014-03-11 17:03:07 +1100 116) irr::core::stringw Achievement::getProgressAsString() const
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 117) {
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 118)     int progress = 0;
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 119)     std::map<std::string, int>::const_iterator iter;
cecb7252 (hiker        2014-03-13 17:12:51 +1100 120) 
cecb7252 (hiker        2014-03-13 17:12:51 +1100 121)     // For now return N/N in case of an achieved achievement.
cecb7252 (hiker        2014-03-13 17:12:51 +1100 122)     if (m_achieved)
cecb7252 (hiker        2014-03-13 17:12:51 +1100 123)         return getInfo()->toString() +"/" + getInfo()->toString();
cecb7252 (hiker        2014-03-13 17:12:51 +1100 124) 
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 125)     switch (m_achievement_info->getCheckType())
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 126)     {
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 127)     case AchievementInfo::AC_ALL_AT_LEAST:
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 128)         for (iter = m_progress_map.begin(); iter != m_progress_map.end(); ++iter)
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 129)         {
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 130)             progress += iter->second;
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 131)         }
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 132)         break;
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 133)     case AchievementInfo::AC_ONE_AT_LEAST:
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 134)         for (iter = m_progress_map.begin(); iter != m_progress_map.end(); ++iter)
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 135)         {
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 136)             if(iter->second>progress) progress = iter->second;
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 137)         }
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 138)         break;
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 139)     default:
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 140)         Log::fatal("Achievement", "Missing getProgressAsString for type %d.",
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 141)                    m_achievement_info->getCheckType());
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 142)     }
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 143)     return StringUtils::toWString(progress) + "/" + getInfo()->toString();
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 144) }   // getProgressAsString
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 145) 
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 146) // ----------------------------------------------------------------------------
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 147) /** Increases the value of a key by a specified amount, but make sure to not
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 148)  *  increase the value above the goal (otherwise the achievement progress
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 149)  *  could be 12/10 (e.g. if one track is used 12 times for the Christoffel
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 150)  *  achievement), even though the achievement is not achieved.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 151)  *  \param key The key whose value is increased.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 152)  *  \param increase Amount to add to the value of this key.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 153)  */
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 154) void Achievement::increase(const std::string & key, int increase)
178fc861 (unitraxx     2013-09-04 01:57:04 +0000 155) {
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 156)     std::map<std::string, int>::iterator it;
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 157)     it = m_progress_map.find(key);
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 158)     if (it != m_progress_map.end())
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 159)     {
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 160)         it->second += increase;
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 161)         if (it->second > m_achievement_info->getGoalValue(key))
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 162)             it->second = m_achievement_info->getGoalValue(key);
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 163)     }
b214799a (hiker        2014-02-21 22:15:36 +1100 164)     else
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 165)     {
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 166)         if (increase>m_achievement_info->getGoalValue(key))
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 167)             increase = m_achievement_info->getGoalValue(key);
b214799a (hiker        2014-02-21 22:15:36 +1100 168)         m_progress_map[key] = increase;
36c9c4d6 (hiker        2014-02-26 10:36:02 +1100 169)     }
f8a462a3 (hiker        2014-02-25 17:20:24 +1100 170)     check();
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 171) }   // increase
178fc861 (unitraxx     2013-09-04 01:57:04 +0000 172) 
b214799a (hiker        2014-02-21 22:15:36 +1100 173) // ----------------------------------------------------------------------------
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 174) /** Called at the end of a race to potentially reset values.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 175)  */
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 176) void Achievement::onRaceEnd()
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 177) {
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 178)     if(m_achievement_info->needsResetAfterRace())
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 179)         reset();
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 180) }   // onRaceEnd
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 181) 
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 182) // ----------------------------------------------------------------------------
60f1d8ae (Csaba Molnar 2014-03-17 22:07:55 +0100 183) /** Called at the end of a lap to potentially reset values.
60f1d8ae (Csaba Molnar 2014-03-17 22:07:55 +0100 184) */
60f1d8ae (Csaba Molnar 2014-03-17 22:07:55 +0100 185) void Achievement::onLapEnd()
60f1d8ae (Csaba Molnar 2014-03-17 22:07:55 +0100 186) {
60f1d8ae (Csaba Molnar 2014-03-17 22:07:55 +0100 187)     if (m_achievement_info->needsResetAfterLap())
60f1d8ae (Csaba Molnar 2014-03-17 22:07:55 +0100 188)         reset();
60f1d8ae (Csaba Molnar 2014-03-17 22:07:55 +0100 189) }   // onLapEnd
60f1d8ae (Csaba Molnar 2014-03-17 22:07:55 +0100 190) 
60f1d8ae (Csaba Molnar 2014-03-17 22:07:55 +0100 191) // ----------------------------------------------------------------------------
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 192) /** Checks if this achievement has been achieved.
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 193)  */
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 194) void Achievement::check()
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 195) {
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 196)     if(m_achieved)
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 197)         return;
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 198) 
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 199)     if(m_achievement_info->checkCompletion(this))
b214799a (hiker        2014-02-21 22:15:36 +1100 200)     {
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 201)         //show achievement
4cf20ff7 (hiker        2015-01-30 16:18:26 +1100 202)         core::stringw s = _("Completed achievement \"%s\".", 
06c8089d (Flakebi      2015-03-30 00:38:59 +0200 203)                             m_achievement_info->getName());
6231e618 (hiker        2014-06-23 09:13:44 +1000 204)         MessageQueue::add(MessageQueue::MT_ACHIEVEMENT, s);
ac261900 (hiker        2014-02-26 09:16:40 +1100 205) 
9b1b6668 (hiker        2014-04-07 13:19:07 +1000 206)         // Sends a confirmation to the server that an achievement has been
9b1b6668 (hiker        2014-04-07 13:19:07 +1000 207)         // completed, if a user is signed in.
3a5a0a56 (hiker        2014-04-11 16:20:04 +1000 208)         if (PlayerManager::isCurrentLoggedIn())
9b1b6668 (hiker        2014-04-07 13:19:07 +1000 209)         {
9b1b6668 (hiker        2014-04-07 13:19:07 +1000 210)             Online::HTTPRequest * request = new Online::HTTPRequest(true);
502987d3 (hiker        2014-04-10 16:32:58 +1000 211)             PlayerManager::setUserDetails(request, "achieving");
9b1b6668 (hiker        2014-04-07 13:19:07 +1000 212)             request->addParameter("achievementid", m_id);
9b1b6668 (hiker        2014-04-07 13:19:07 +1000 213)             request->queue();
9b1b6668 (hiker        2014-04-07 13:19:07 +1000 214)         }
9b1b6668 (hiker        2014-04-07 13:19:07 +1000 215) 
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 216)         m_achieved = true;
fc45d76d (unitraxx     2013-09-11 19:23:54 +0000 217)     }
5fc300d7 (hiker        2014-02-24 08:21:15 +1100 218) }   // check
fc45d76d (unitraxx     2013-09-11 19:23:54 +0000 219) 
