Massive refactor in challenge code to allow having more than 1 progression

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10349 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2011-12-05 22:00:42 +00:00
parent b5fef48c61
commit 0455efd20d
26 changed files with 702 additions and 466 deletions

File diff suppressed because one or more lines are too long

View File

@ -21,7 +21,9 @@
#include <fstream>
#include "challenges/challenge_data.hpp"
#include "io/xml_node.hpp"
#include "io/xml_writer.hpp"
#include "karts/kart_properties_manager.hpp"
#include "karts/kart_properties.hpp"
#include "race/grand_prix_manager.hpp"
@ -31,141 +33,12 @@
#include "utils/translation.hpp"
#include "utils/string_utils.hpp"
const irr::core::stringw Challenge::UnlockableFeature::getUnlockedMessage() const
{
switch (m_type)
{
case UNLOCK_TRACK:
{ // {} avoids compiler warning
const Track* track = track_manager->getTrack(m_name);
// shouldn't happen but let's avoid crashes as much as possible...
if (track == NULL) return irr::core::stringw( L"????" );
return _("New track '%s' now available", core::stringw(track->getName()));
break;
}
case UNLOCK_MODE:
{
return _("New game mode '%s' now available", m_user_name);
}
case UNLOCK_GP:
{
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(m_name);
// shouldn't happen but let's avoid crashes as much as possible...
if (gp == NULL) return irr::core::stringw( L"????" );
const irr::core::stringw& gp_user_name = gp->getName();
return _("New Grand Prix '%s' now available", gp_user_name);
}
case UNLOCK_DIFFICULTY:
{
return _("New difficulty '%s' now available", m_user_name);
}
case UNLOCK_KART:
{
const KartProperties* kp =
kart_properties_manager->getKart(m_name);
// shouldn't happen but let's avoid crashes as much as possible...
if (kp == NULL) return irr::core::stringw( L"????" );
return _("New kart '%s' now available", core::stringw(kp->getName()));
}
default:
assert(false);
return L"";
} // switch
} // UnlockableFeature::getUnlockedMessage
//-----------------------------------------------------------------------------
/** Sets that the given track will be unlocked if this challenge
* is unlocked.
* \param track_name Name of the track to unlock.
*/
void Challenge::addUnlockTrackReward(const std::string &track_name)
{
if (track_manager->getTrack(track_name) == NULL)
{
throw std::runtime_error(StringUtils::insertValues("Challenge refers to unknown track <%s>", track_name.c_str()));
}
UnlockableFeature feature;
feature.m_name = track_name;
feature.m_type = UNLOCK_TRACK;
m_feature.push_back(feature);
} // addUnlockTrackReward
//-----------------------------------------------------------------------------
void Challenge::addUnlockModeReward(const std::string &internal_mode_name,
const irr::core::stringw &user_mode_name)
{
UnlockableFeature feature;
feature.m_name = internal_mode_name;
feature.m_type = UNLOCK_MODE;
feature.m_user_name = user_mode_name;
m_feature.push_back(feature);
} // addUnlockModeReward
//-----------------------------------------------------------------------------
void Challenge::addUnlockGPReward(const std::string &gp_name)
{
if (grand_prix_manager->getGrandPrix(gp_name) == NULL)
{
throw std::runtime_error(StringUtils::insertValues("Challenge refers to unknown Grand Prix <%s>", gp_name.c_str()));
}
UnlockableFeature feature;
feature.m_name = gp_name.c_str();
feature.m_type = UNLOCK_GP;
m_feature.push_back(feature);
} // addUnlockGPReward
//-----------------------------------------------------------------------------
void Challenge::addUnlockDifficultyReward(const std::string &internal_name,
const irr::core::stringw &user_name)
{
UnlockableFeature feature;
feature.m_name = internal_name;
feature.m_type = UNLOCK_DIFFICULTY;
feature.m_user_name = user_name;
m_feature.push_back(feature);
} // addUnlockDifficultyReward
//-----------------------------------------------------------------------------
void Challenge::addUnlockKartReward(const std::string &internal_name,
const irr::core::stringw &user_name)
{
try
{
kart_properties_manager->getKartId(internal_name);
}
catch (std::exception& e)
{
(void)e; // avoid compiler warning
throw std::runtime_error(StringUtils::insertValues("Challenge refers to unknown kart <%s>", internal_name.c_str()));
}
UnlockableFeature feature;
feature.m_name = internal_name;
feature.m_type = UNLOCK_KART;
feature.m_user_name = user_name;
m_feature.push_back(feature);
} // addUnlockKartReward
//-----------------------------------------------------------------------------
/** Loads the state for a challenge object (esp. m_state), and calls the
* virtual function loadAdditionalInfo for additional information
/** Loads the state for a challenge object (esp. m_state)
*/
void Challenge::load(const XMLNode* challengesNode)
{
const XMLNode* node = challengesNode->getNode( getId() );
const XMLNode* node = challengesNode->getNode( m_data->getId() );
if(node == NULL) return;
// See if the challenge is solved (it's activated later from the
@ -173,15 +46,12 @@ void Challenge::load(const XMLNode* challengesNode)
bool finished=false;
node->get("solved", &finished);
m_state = finished ? CH_SOLVED : CH_INACTIVE;
if(!finished) loadAdditionalInfo(node);
} // load
//-----------------------------------------------------------------------------
void Challenge::save(std::ofstream& writer)
void Challenge::save(XMLWriter& writer)
{
writer << " <" << getId() << " solved=\""
<< (isSolved() ? "true" : "false") << "\"";
if(!isSolved()) saveAdditionalInfo(writer);
writer << " />\n";
writer << L" <" << core::stringw(m_data->getId().c_str()) << L" solved=\""
<< (isSolved() ? L"true" : L"false") << L"\"";
writer << L" />\n";
} // save

View File

@ -35,92 +35,29 @@
#include "utils/translation.hpp"
class XMLNode;
class XMLWriter;
class ChallengeData;
/**
* \brief A class for all challenges
* \brief The state of a challenge for one player
* \ingroup challenges
*/
class Challenge : public NoCopy
{
public:
enum REWARD_TYPE {UNLOCK_TRACK,
UNLOCK_GP,
UNLOCK_MODE,
UNLOCK_KART,
UNLOCK_DIFFICULTY};
// ------------------------------------------------------------------------
class UnlockableFeature
{
public:
std::string m_name; // internal name
irr::core::stringw m_user_name; // not all types of feature have one
REWARD_TYPE m_type;
const irr::core::stringw getUnlockedMessage() const;
}; // UnlockableFeature
// ------------------------------------------------------------------------
private:
enum {CH_INACTIVE, // challenge not yet possible
CH_ACTIVE, // challenge possible, but not yet solved
CH_SOLVED} m_state; // challenge was solved
/** Short, internal name for this challenge. */
std::string m_id;
/** Name used in menu for this challenge. */
irr::core::stringw m_name;
/** Message the user gets when the feature is not yet unlocked. */
irr::core::stringw m_challenge_description;
/** Features to unlock. */
std::vector<UnlockableFeature> m_feature;
/** What needs to be done before accessing this challenge. */
std::vector<std::string> m_prerequisites;
ChallengeData* m_data;
public:
Challenge(const std::string &id, const std::string &name);
Challenge() : m_state(CH_INACTIVE), m_id(""), m_name("")
{ }
Challenge(ChallengeData* data) : m_state(CH_INACTIVE)
{ m_data = data; }
virtual ~Challenge() {};
void addUnlockTrackReward(const std::string &track_name);
void addUnlockModeReward(const std::string &internal_mode_name,
const irr::core::stringw &user_mode_name);
void addUnlockGPReward(const std::string &gp_name);
void addUnlockDifficultyReward(const std::string &internal_name,
const irr::core::stringw &user_name);
void addUnlockKartReward(const std::string &internal_name,
const irr::core::stringw &user_name);
void load(const XMLNode* config);
void save(std::ofstream& writer);
// These functions are meant for customisation, e.g. load/save
// additional state information specific to the challenge
virtual void loadAdditionalInfo(const XMLNode* config) {};
virtual void saveAdditionalInfo(std::ofstream& writer) {};
// ------------------------------------------------------------------------
/** Returns the id of the challenge. */
const std::string &getId() const { return m_id; }
// ------------------------------------------------------------------------
/** Returns the name of the challenge. */
const irr::core::stringw getName() const
{ return irr::core::stringw(_(m_name.c_str())); }
// ------------------------------------------------------------------------
/** Sets the name of the challenge. */
void setName(const irr::core::stringw & s) { m_name = s; }
// ------------------------------------------------------------------------
/** Sets the id of this challenge. */
void setId(const std::string& s) { m_id = s; }
// ------------------------------------------------------------------------
const std::vector<UnlockableFeature>&
getFeatures() const { return m_feature; }
// ------------------------------------------------------------------------
void setChallengeDescription(const irr::core::stringw& d)
{m_challenge_description=d; }
// ------------------------------------------------------------------------
const irr::core::stringw
getChallengeDescription() const
{return _(m_challenge_description.c_str()); }
// ------------------------------------------------------------------------
void addDependency(const std::string id) {m_prerequisites.push_back(id);}
void save(XMLWriter& writer);
// ------------------------------------------------------------------------
bool isSolved() const {return m_state==CH_SOLVED; }
// ------------------------------------------------------------------------
@ -130,9 +67,6 @@ public:
// ------------------------------------------------------------------------
void setActive() {m_state = CH_ACTIVE; }
// ------------------------------------------------------------------------
const std::vector<std::string>&
getPrerequisites() const {return m_prerequisites; }
// ------------------------------------------------------------------------
/** These functions are called when a race is finished. It allows
* the challenge to unlock features (when returning true), otherwise
* the feature remains locked. */
@ -142,11 +76,7 @@ public:
* the challenge to unlock features (when returning true), otherwise
* the feature remains locked. */
virtual bool grandPrixFinished() {return false; }
// ------------------------------------------------------------------------
/** Sets the right parameters in RaceManager to try this challenge */
virtual void setRace() const = 0;
// ------------------------------------------------------------------------
/** Checks if a challenge is valid. */
virtual void check() const = 0;
ChallengeData* getData() { return m_data; }
};
#endif

View File

@ -145,11 +145,11 @@ ChallengeData::ChallengeData(const std::string& filename)
if (grand_prix_manager->getGrandPrix(m_gp_id) == NULL) error("gp");
}
getUnlocks(root, "unlock-track", Challenge::UNLOCK_TRACK);
getUnlocks(root, "unlock-gp", Challenge::UNLOCK_GP );
getUnlocks(root, "unlock-mode", Challenge::UNLOCK_MODE );
getUnlocks(root, "unlock-difficulty", Challenge::UNLOCK_DIFFICULTY);
getUnlocks(root, "unlock-kart", Challenge::UNLOCK_KART);
getUnlocks(root, "unlock-track", ChallengeData::UNLOCK_TRACK);
getUnlocks(root, "unlock-gp", ChallengeData::UNLOCK_GP );
getUnlocks(root, "unlock-mode", ChallengeData::UNLOCK_MODE );
getUnlocks(root, "unlock-difficulty", ChallengeData::UNLOCK_DIFFICULTY);
getUnlocks(root, "unlock-kart", ChallengeData::UNLOCK_KART);
if (getFeatures().size() == 0)
{
@ -349,3 +349,134 @@ bool ChallengeData::grandPrixFinished()
return true;
} // grandPrixFinished
// ----------------------------------------------------------------------------
const irr::core::stringw ChallengeData::UnlockableFeature::getUnlockedMessage() const
{
switch (m_type)
{
case UNLOCK_TRACK:
{ // {} avoids compiler warning
const Track* track = track_manager->getTrack(m_name);
// shouldn't happen but let's avoid crashes as much as possible...
if (track == NULL) return irr::core::stringw( L"????" );
return _("New track '%s' now available", core::stringw(track->getName()));
break;
}
case UNLOCK_MODE:
{
return _("New game mode '%s' now available", m_user_name);
}
case UNLOCK_GP:
{
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(m_name);
// shouldn't happen but let's avoid crashes as much as possible...
if (gp == NULL) return irr::core::stringw( L"????" );
const irr::core::stringw& gp_user_name = gp->getName();
return _("New Grand Prix '%s' now available", gp_user_name);
}
case UNLOCK_DIFFICULTY:
{
return _("New difficulty '%s' now available", m_user_name);
}
case UNLOCK_KART:
{
const KartProperties* kp =
kart_properties_manager->getKart(m_name);
// shouldn't happen but let's avoid crashes as much as possible...
if (kp == NULL) return irr::core::stringw( L"????" );
return _("New kart '%s' now available", core::stringw(kp->getName()));
}
default:
assert(false);
return L"";
} // switch
} // UnlockableFeature::getUnlockedMessage
//-----------------------------------------------------------------------------
/** Sets that the given track will be unlocked if this challenge
* is unlocked.
* \param track_name Name of the track to unlock.
*/
void ChallengeData::addUnlockTrackReward(const std::string &track_name)
{
if (track_manager->getTrack(track_name) == NULL)
{
throw std::runtime_error(StringUtils::insertValues("Challenge refers to unknown track <%s>", track_name.c_str()));
}
UnlockableFeature feature;
feature.m_name = track_name;
feature.m_type = UNLOCK_TRACK;
m_feature.push_back(feature);
} // addUnlockTrackReward
//-----------------------------------------------------------------------------
void ChallengeData::addUnlockModeReward(const std::string &internal_mode_name,
const irr::core::stringw &user_mode_name)
{
UnlockableFeature feature;
feature.m_name = internal_mode_name;
feature.m_type = UNLOCK_MODE;
feature.m_user_name = user_mode_name;
m_feature.push_back(feature);
} // addUnlockModeReward
//-----------------------------------------------------------------------------
void ChallengeData::addUnlockGPReward(const std::string &gp_name)
{
if (grand_prix_manager->getGrandPrix(gp_name) == NULL)
{
throw std::runtime_error(StringUtils::insertValues("Challenge refers to unknown Grand Prix <%s>", gp_name.c_str()));
}
UnlockableFeature feature;
feature.m_name = gp_name.c_str();
feature.m_type = UNLOCK_GP;
m_feature.push_back(feature);
} // addUnlockGPReward
//-----------------------------------------------------------------------------
void ChallengeData::addUnlockDifficultyReward(const std::string &internal_name,
const irr::core::stringw &user_name)
{
UnlockableFeature feature;
feature.m_name = internal_name;
feature.m_type = UNLOCK_DIFFICULTY;
feature.m_user_name = user_name;
m_feature.push_back(feature);
} // addUnlockDifficultyReward
//-----------------------------------------------------------------------------
void ChallengeData::addUnlockKartReward(const std::string &internal_name,
const irr::core::stringw &user_name)
{
try
{
kart_properties_manager->getKartId(internal_name);
}
catch (std::exception& e)
{
(void)e; // avoid compiler warning
throw std::runtime_error(StringUtils::insertValues("Challenge refers to unknown kart <%s>", internal_name.c_str()));
}
UnlockableFeature feature;
feature.m_name = internal_name;
feature.m_type = UNLOCK_KART;
feature.m_user_name = user_name;
m_feature.push_back(feature);
} // addUnlockKartReward

View File

@ -29,10 +29,30 @@
#include "race/race_manager.hpp"
/**
* \brief the description of one challenge
* \ingroup challenges
*/
class ChallengeData : public Challenge
class ChallengeData
{
public:
enum REWARD_TYPE {UNLOCK_TRACK,
UNLOCK_GP,
UNLOCK_MODE,
UNLOCK_KART,
UNLOCK_DIFFICULTY};
// ------------------------------------------------------------------------
class UnlockableFeature
{
public:
std::string m_name; // internal name
irr::core::stringw m_user_name; // not all types of feature have one
REWARD_TYPE m_type;
const irr::core::stringw getUnlockedMessage() const;
}; // UnlockableFeature
// ------------------------------------------------------------------------
private:
RaceManager::MajorRaceModeType m_major;
RaceManager::MinorRaceModeType m_minor;
@ -49,9 +69,21 @@ private:
int m_version;
void getUnlocks(const XMLNode *root, const std::string &type,
Challenge::REWARD_TYPE reward);
ChallengeData::REWARD_TYPE reward);
void error(const char *id) const;
/** Short, internal name for this challenge. */
std::string m_id;
/** Name used in menu for this challenge. */
irr::core::stringw m_name;
/** Message the user gets when the feature is not yet unlocked. */
irr::core::stringw m_challenge_description;
/** Features to unlock. */
std::vector<UnlockableFeature> m_feature;
/** What needs to be done before accessing this challenge. */
std::vector<std::string> m_prerequisites;
public:
#ifdef WIN32
ChallengeData(const std::string& filename);
@ -59,6 +91,8 @@ public:
ChallengeData(const std::string& filename) throw(std::runtime_error);
#endif
virtual ~ChallengeData() {}
/** sets the right parameters in RaceManager to try this challenge */
void setRace() const;
@ -67,6 +101,44 @@ public:
virtual bool grandPrixFinished();
/** Returns the version number of this challenge. */
int getVersion() const { return m_version; }
const std::vector<UnlockableFeature>&
getFeatures() const { return m_feature; }
void setChallengeDescription(const irr::core::stringw& d)
{m_challenge_description=d; }
const irr::core::stringw getChallengeDescription() const
{return _(m_challenge_description.c_str()); }
void addDependency(const std::string id) {m_prerequisites.push_back(id);}
const std::vector<std::string>&
getPrerequisites() const {return m_prerequisites; }
/** Returns the id of the challenge. */
const std::string &getId() const { return m_id; }
/** Returns the name of the challenge. */
const irr::core::stringw getName() const
{ return irr::core::stringw(_(m_name.c_str())); }
/** Sets the name of the challenge. */
void setName(const irr::core::stringw & s) { m_name = s; }
/** Sets the id of this challenge. */
void setId(const std::string& s) { m_id = s; }
void addUnlockTrackReward(const std::string &track_name);
void addUnlockModeReward(const std::string &internal_mode_name,
const irr::core::stringw &user_mode_name);
void addUnlockGPReward(const std::string &gp_name);
void addUnlockDifficultyReward(const std::string &internal_name,
const irr::core::stringw &user_name);
void addUnlockKartReward(const std::string &internal_name,
const irr::core::stringw &user_name);
}; // ChallengeData
#endif // HEADER_CHALLENGE_DATA_HPP

View File

@ -0,0 +1,216 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 SuperTuxKart-Team
//
// 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 "challenges/game_slot.hpp"
#include "challenges/challenge_data.hpp"
#include "challenges/unlock_manager.hpp"
#include "io/xml_writer.hpp"
//-----------------------------------------------------------------------------
bool GameSlot::isLocked(const std::string& feature)
{
return m_locked_features.find(feature)!=m_locked_features.end();
} // featureIsLocked
//-----------------------------------------------------------------------------
const std::vector<const ChallengeData*> GameSlot::getUnlockedFeatures()
{
std::vector<const ChallengeData*> out;
std::map<std::string, Challenge*>::const_iterator i;
for(i = m_challenges_state.begin();
i != m_challenges_state.end(); i++)
{
if (i->second->isSolved()) out.push_back(i->second->getData());
}
return out;
}
//-----------------------------------------------------------------------------
const std::vector<const ChallengeData*> GameSlot::getLockedChallenges()
{
std::vector<const ChallengeData*> out;
std::map<std::string, Challenge*>::const_iterator i;
for(i = m_challenges_state.begin();
i != m_challenges_state.end(); i++)
{
if (!i->second->isSolved()) out.push_back(i->second->getData());
}
return out;
}
//-----------------------------------------------------------------------------
void GameSlot::computeActive()
{
std::map<std::string, Challenge*>::const_iterator i;
for(i = m_challenges_state.begin();
i != m_challenges_state.end(); i++)
{
// Changed challenge
// -----------------
if((i->second)->isSolved())
{
// The constructor calls computeActive, which actually locks
// all features, so unlock the solved ones (and don't try to
// save the state, since we are currently reading it)
unlockFeature(i->second, /*save*/ false);
continue;
}
// Otherwise lock the feature, and check if the challenge is active
// ----------------------------------------------------------------
lockFeature(i->second);
std::vector<std::string> pre_req=(i->second)->getData()->getPrerequisites();
bool allSolved=true;
for(std::vector<std::string>::iterator pre =pre_req.begin();
pre!=pre_req.end(); pre++)
{
const Challenge* p = m_challenges_state[*pre];
if(!p)
{
fprintf(stderr,"Challenge prerequisite '%s' of '%s' not found - ignored\n",
pre->c_str(), i->first.c_str());
//continue;
allSolved=false;
break;
}
else if(!p->isSolved())
{
allSolved=false;
break;
}
} // for all pre in pre_req
if(allSolved)
{
i->second->setActive();
} // if solved
} // for i
clearUnlocked();
} // computeActive
//-----------------------------------------------------------------------------
void GameSlot::lockFeature(Challenge *challenge)
{
const std::vector<ChallengeData::UnlockableFeature>& features = challenge->getData()->getFeatures();
const unsigned int amount = (unsigned int)features.size();
for(unsigned int n=0; n<amount; n++)
m_locked_features[features[n].m_name]=true;
} // lockFeature
//-----------------------------------------------------------------------------
void GameSlot::unlockFeature(Challenge* c, bool do_save)
{
const unsigned int amount = (unsigned int)c->getData()->getFeatures().size();
for(unsigned int n=0; n<amount; n++)
{
std::string feature = c->getData()->getFeatures()[n].m_name;
std::map<std::string,bool>::iterator p=m_locked_features.find(feature);
if(p==m_locked_features.end())
{
//fprintf(stderr,"Unlocking feature '%s' failed: feature is not locked.\n",
// (feature).c_str());
return;
}
m_locked_features.erase(p);
}
// Add to list of recently unlocked features
m_unlocked_features.push_back(c->getData());
c->setSolved(); // reset isActive flag
// Save the new unlock information
if(do_save) unlock_manager->save();
} // unlockFeature
//-----------------------------------------------------------------------------
std::vector<const ChallengeData*> GameSlot::getActiveChallenges()
{
computeActive();
std::vector<const ChallengeData*> out;
std::map<std::string, Challenge*>::const_iterator i;
for(i = m_challenges_state.begin();
i != m_challenges_state.end(); i++)
{
if (i->second->isActive()) out.push_back(i->second->getData());
}
return out;
} // getActiveChallenges
//-----------------------------------------------------------------------------
/** This is called when a race is finished. Call all active challenges
*/
void GameSlot::raceFinished()
{
std::map<std::string, Challenge*>::const_iterator i;
for(i = m_challenges_state.begin();
i != m_challenges_state.end(); i++)
{
if(i->second->isActive() && i->second->raceFinished())
{
unlockFeature(i->second);
} // if isActive && challenge solved
}
//race_manager->setCoinTarget(0); //reset
} // raceFinished
//-----------------------------------------------------------------------------
void GameSlot::grandPrixFinished()
{
std::map<std::string, Challenge*>::const_iterator i;
for(i = m_challenges_state.begin();
i != m_challenges_state.end(); i++)
{
if(i->second->isActive() && i->second->grandPrixFinished())
{
printf("===== A FEATURE WAS UNLOCKED BECAUSE YOU WON THE GP!! ==\n");
unlockFeature(i->second);
}
}
race_manager->setCoinTarget(0);
} // grandPrixFinished
//-----------------------------------------------------------------------------
void GameSlot::save(XMLWriter& out)
{
out << L" <gameslot player=\"" << m_player_name.c_str() << L"\" kart=\""
<< m_kart_ident.c_str() << L"\">\n";
std::map<std::string, Challenge*>::const_iterator i;
for(i = m_challenges_state.begin();
i != m_challenges_state.end(); i++)
{
i->second->save(out);
}
out << " </gameslot>\n";
}

View File

@ -0,0 +1,97 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 SuperTuxKart-Team
//
// 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 GAME_SLOT_HPP
#define GAME_SLOT_HPP
#include <string>
#include <map>
#include <vector>
#include <irrString.h>
class ChallengeData;
class Challenge;
class XMLWriter;
/**
* \ingroup challenges
* This class contains the progression through challenges for one game slot
*/
class GameSlot
{
irr::core::stringw m_player_name;
std::string m_kart_ident;
/** Contains whether each feature of the challenge is locked or unlocked */
std::map<std::string, bool> m_locked_features;
/** Recently unlocked features (they are waiting here
* until they are shown to the user) */
std::vector<const ChallengeData*> m_unlocked_features;
std::map<std::string, Challenge*> m_challenges_state;
friend class UnlockManager;
void computeActive();
public:
GameSlot(const irr::core::stringw& player_name)
{
m_player_name = player_name;
}
const irr::core::stringw& getPlayerName() const { return m_player_name; }
const std::string& getKartIdent () const { return m_kart_ident; }
void setKartIdent(const std::string& kart_ident) { m_kart_ident = kart_ident; }
/** Returns the list of recently unlocked features (e.g. call at the end of a
race to know if any features were unlocked) */
const std::vector<const ChallengeData*>
getRecentlyUnlockedFeatures() {return m_unlocked_features;}
/** Clear the list of recently unlocked challenges */
void clearUnlocked () {m_unlocked_features.clear(); }
/** Returns a complete list of all solved challenges */
const std::vector<const ChallengeData*> getUnlockedFeatures();
/** Returns the list of currently inaccessible (locked) challenges */
const std::vector<const ChallengeData*> getLockedChallenges();
bool isLocked (const std::string& feature);
void lockFeature (Challenge *challenge);
void unlockFeature (Challenge* c, bool do_save=true);
std::vector<const ChallengeData*> getActiveChallenges();
void raceFinished ();
void grandPrixFinished ();
void save (XMLWriter& file);
};
#endif

View File

@ -27,9 +27,11 @@
#include "audio/sfx_base.hpp"
#include "audio/sfx_manager.hpp"
#include "config/player.hpp"
#include "config/user_config.hpp"
#include "challenges/challenge_data.hpp"
#include "io/file_manager.hpp"
#include "io/xml_writer.hpp"
#include "karts/kart_properties_manager.hpp"
#include "race/race_manager.hpp"
#include "tracks/track_manager.hpp"
@ -45,6 +47,8 @@ UnlockManager::UnlockManager()
// in main).
unlock_manager=this;
m_current_game_slot = 0;
m_locked_sound = sfx_manager->createSoundSource("locked");
@ -173,19 +177,6 @@ void UnlockManager::addChallenge(const std::string& filename)
} // addChallenge
//-----------------------------------------------------------------------------
std::vector<const ChallengeData*> UnlockManager::getActiveChallenges()
{
computeActive();
std::vector<const ChallengeData*> all_active;
for(AllChallengesType::iterator i =m_all_challenges.begin();
i!=m_all_challenges.end(); i++)
{
if(i->second->isActive()) all_active.push_back(i->second);
}
return all_active;
} // getActiveChallenges
//-----------------------------------------------------------------------------
const ChallengeData* UnlockManager::getChallenge(const std::string& id)
{
@ -204,29 +195,52 @@ void UnlockManager::load()
{
std::cerr << "Challenge file '" << filename << "' will be created."
<< std::endl;
createSlotsIfNeeded();
save();
if (root) delete root;
computeActive();
return;
}
for(AllChallengesType::iterator i =m_all_challenges.begin();
std::vector<XMLNode*> xml_game_slots;
root->getNodes("gameslot", xml_game_slots);
for (unsigned int n=0; n<xml_game_slots.size(); n++)
{
core::stringw player_name;
xml_game_slots[n]->get("player", &player_name);
GameSlot* slot = new GameSlot(player_name);
std::string kart_id;
xml_game_slots[n]->get("kart", &kart_id);
slot->setKartIdent(kart_id);
m_game_slots.push_back(slot);
for(AllChallengesType::iterator i = m_all_challenges.begin();
i!=m_all_challenges.end(); i++)
{
i->second->load(root);
ChallengeData* curr = i->second;
Challenge* state = new Challenge(curr);
slot->m_challenges_state[curr->getId()] = state;
state->load(root);
}
computeActive();
slot->computeActive();
}
bool something_changed = createSlotsIfNeeded();
if (something_changed) save();
delete root;
} // load
//-----------------------------------------------------------------------------
void UnlockManager::save()
{
std::ofstream challenge_file;
std::string filename = file_manager->getChallengeFile("challenges.xml");
challenge_file.open(filename.c_str());
XMLWriter challenge_file(filename.c_str());
if(!challenge_file.is_open())
{
@ -237,16 +251,61 @@ void UnlockManager::save()
challenge_file << "<?xml version=\"1.0\"?>\n";
challenge_file << "<challenges>\n";
for(AllChallengesType::iterator i = m_all_challenges.begin();
i!= m_all_challenges.end(); i++)
GameSlot* curr;
for_in (curr, m_game_slots)
{
i->second->save(challenge_file);
curr->save(challenge_file);
}
challenge_file << "</challenges>\n\n";
challenge_file.close();
} // save
//-----------------------------------------------------------------------------
bool UnlockManager::createSlotsIfNeeded()
{
bool something_changed = false;
// make sure all players have at least one game slot associated
PtrVector<PlayerProfile>& players = UserConfigParams::m_all_players;
for (int n=0; n<players.size(); n++)
{
printf("Checking if a game slot exists for player %s\n", core::stringc(players[n].getName().c_str()).c_str());
bool exists = false;
GameSlot* curr_slot;
for_in(curr_slot, m_game_slots)
{
if (curr_slot->getPlayerName() == players[n].getName())
{
exists = true;
break;
}
}
if (!exists)
{
printf("==> No, creating one\n");
GameSlot* slot = new GameSlot(players[n].getName());
for(AllChallengesType::iterator i = m_all_challenges.begin();
i!=m_all_challenges.end(); i++)
{
ChallengeData* cd = i->second;
slot->m_challenges_state[cd->getId()] = new Challenge(cd);
}
slot->computeActive();
m_game_slots.push_back(slot);
something_changed = true;
}
}
return something_changed;
}
//-----------------------------------------------------------------------------
void UnlockManager::playLockSound() const
{
@ -264,150 +323,5 @@ bool UnlockManager::isSupportedVersion(const ChallengeData &challenge)
return (challenge.getVersion()>=1 && challenge.getVersion()<=1);
} // isSupportedVersion
//-----------------------------------------------------------------------------
void UnlockManager::computeActive()
{
for(AllChallengesType::iterator i =m_all_challenges.begin();
i!=m_all_challenges.end(); i++)
{
// Changed challenge
// -----------------
if((i->second)->isSolved())
{
// The constructor calls computeActive, which actually locks
// all features, so unlock the solved ones (and don't try to
// save the state, since we are currently reading it)
unlockFeature(i->second, /*save*/ false);
continue;
}
// Otherwise lock the feature, and check if the challenge is active
// ----------------------------------------------------------------
lockFeature(i->second);
std::vector<std::string> pre_req=(i->second)->getPrerequisites();
bool allSolved=true;
for(std::vector<std::string>::iterator pre =pre_req.begin();
pre!=pre_req.end(); pre++)
{
const ChallengeData *p = getChallenge(*pre);
if(!p)
{
fprintf(stderr,"Challenge prerequisite '%s' of '%s' not found - ignored\n",
pre->c_str(), i->first.c_str());
//continue;
allSolved=false;
break;
}
else if(!p->isSolved())
{
allSolved=false;
break;
}
} // for all pre in pre_req
if(allSolved)
{
i->second->setActive();
} // if solved
} // for i
clearUnlocked();
} // computeActive
//-----------------------------------------------------------------------------
/** This is called when a race is finished. Call all active challenges
*/
void UnlockManager::raceFinished()
{
for(AllChallengesType::iterator i =m_all_challenges.begin();
i!=m_all_challenges.end(); i++)
{
if(i->second->isActive() && i->second->raceFinished())
{
unlockFeature(i->second);
} // if isActive && challenge solved
}
//race_manager->setCoinTarget(0); //reset
} // raceFinished
//-----------------------------------------------------------------------------
void UnlockManager::grandPrixFinished()
{
for(AllChallengesType::iterator i =m_all_challenges.begin();
i!=m_all_challenges.end(); i++)
{
if(i->second->isActive() && i->second->grandPrixFinished())
{
std::cout << "===== A FEATURE WAS UNLOCKED BECAUSE YOU WON THE GP!! ==\n";
unlockFeature(i->second);
}
}
race_manager->setCoinTarget(0);
} // grandPrixFinished
//-----------------------------------------------------------------------------
void UnlockManager::lockFeature(const ChallengeData *challenge)
{
const unsigned int amount = (unsigned int)challenge->getFeatures().size();
for(unsigned int n=0; n<amount; n++)
m_locked_features[challenge->getFeatures()[n].m_name]=true;
} // lockFeature
//-----------------------------------------------------------------------------
void UnlockManager::unlockFeature(ChallengeData* c, bool do_save)
{
const unsigned int amount = (unsigned int)c->getFeatures().size();
for(unsigned int n=0; n<amount; n++)
{
std::string feature = c->getFeatures()[n].m_name;
std::map<std::string,bool>::iterator p=m_locked_features.find(feature);
if(p==m_locked_features.end())
{
//fprintf(stderr,"Unlocking feature '%s' failed: feature is not locked.\n",
// (feature).c_str());
return;
}
m_locked_features.erase(p);
}
// Add to list of recently unlocked features
m_unlocked_features.push_back(c);
c->setSolved(); // reset isActive flag
// Save the new unlock information
if(do_save) save();
} // unlockFeature
//-----------------------------------------------------------------------------
bool UnlockManager::isLocked(const std::string& feature)
{
return m_locked_features.find(feature)!=m_locked_features.end();
} // featureIsLocked
//-----------------------------------------------------------------------------
const std::vector<const ChallengeData*> UnlockManager::getUnlockedFeatures()
{
std::vector<const ChallengeData*> out;
for(AllChallengesType::const_iterator i =m_all_challenges.begin();
i!=m_all_challenges.end(); i++)
{
if (i->second->isSolved()) out.push_back(i->second);
}
return out;
}
//-----------------------------------------------------------------------------
const std::vector<const ChallengeData*> UnlockManager::getLockedChallenges()
{
std::vector<const ChallengeData*> out;
for(AllChallengesType::const_iterator i =m_all_challenges.begin();
i!=m_all_challenges.end(); i++)
{
if (!i->second->isSolved() && !i->second->isActive()) out.push_back(i->second);
}
return out;
}

View File

@ -23,7 +23,10 @@
#include <map>
#include "challenges/challenge_data.hpp"
#include "challenges/game_slot.hpp"
#include "utils/no_copy.hpp"
#include "utils/ptr_vector.hpp"
#include <fstream>
@ -38,15 +41,20 @@ class UnlockManager : public NoCopy
{
private:
SFXBase *m_locked_sound;
typedef std::map<std::string, ChallengeData*> AllChallengesType;
AllChallengesType m_all_challenges;
std::map<std::string, bool> m_locked_features;
std::vector<const ChallengeData*> m_unlocked_features;
void computeActive ();
void load ();
void unlockFeature (ChallengeData* c, bool do_save=true);
typedef std::map<std::string, ChallengeData*> AllChallengesType;
AllChallengesType m_all_challenges;
PtrVector<GameSlot> m_game_slots;
void readAllChallengesInDirs(const std::vector<std::string>* all_dirs);
bool createSlotsIfNeeded();
int m_current_game_slot;
friend class GameSlot;
public:
UnlockManager ();
@ -54,34 +62,18 @@ public:
void addOrFreeChallenge(ChallengeData *c);
void addChallenge (const std::string& filename);
void save ();
std::vector<const ChallengeData*>
getActiveChallenges();
/** Returns the list of recently unlocked features (e.g. call at the end of a
race to know if any features were unlocked) */
const std::vector<const ChallengeData*>
getRecentlyUnlockedFeatures() {return m_unlocked_features;}
/** Clear the list of recently unlocked challenges */
void clearUnlocked () {m_unlocked_features.clear(); }
/** Returns a complete list of all solved challenges */
const std::vector<const ChallengeData*> getUnlockedFeatures();
/** Returns the list of currently inaccessible (locked) challenges */
const std::vector<const ChallengeData*> getLockedChallenges();
const ChallengeData *getChallenge (const std::string& id);
void raceFinished ();
void grandPrixFinished ();
void lockFeature (const ChallengeData *challenge);
bool isLocked (const std::string& feature);
bool isSupportedVersion(const ChallengeData &challenge);
/** Eye- (or rather ear-) candy. Play a sound when user tries to access a locked area */
void playLockSound() const;
GameSlot* getCurrentSlot() { return m_game_slots.get(m_current_game_slot); }
void setCurrentSlot(int slotid) { m_current_game_slot = slotid; }
}; // UnlockManager
extern UnlockManager* unlock_manager;

View File

@ -359,6 +359,7 @@
95E246BE111A2959000C965D /* confirm_resolution_dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95E246BC111A2959000C965D /* confirm_resolution_dialog.cpp */; };
95E5C318148C17E500AD3FCC /* story_mode_lobby.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95E5C316148C17E500AD3FCC /* story_mode_lobby.cpp */; };
95E5C335148C19F500AD3FCC /* story_mode_new.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95E5C333148C19F500AD3FCC /* story_mode_new.cpp */; };
95E5C3C2148C418100AD3FCC /* game_slot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95E5C3C0148C418100AD3FCC /* game_slot.cpp */; };
95E6A0C011DCF37800AE088A /* addons_loading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95E6A0BE11DCF37800AE088A /* addons_loading.cpp */; };
95ECA10010124C5000D47C5F /* button_widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95ECA0EC10124C5000D47C5F /* button_widget.cpp */; };
95ECA10110124C5000D47C5F /* check_box_widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95ECA0EE10124C5000D47C5F /* check_box_widget.cpp */; };
@ -1335,6 +1336,8 @@
95E5C317148C17E500AD3FCC /* story_mode_lobby.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = story_mode_lobby.hpp; path = ../../states_screens/story_mode_lobby.hpp; sourceTree = SOURCE_ROOT; };
95E5C333148C19F500AD3FCC /* story_mode_new.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = story_mode_new.cpp; path = ../../states_screens/dialogs/story_mode_new.cpp; sourceTree = SOURCE_ROOT; };
95E5C334148C19F500AD3FCC /* story_mode_new.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = story_mode_new.hpp; path = ../../states_screens/dialogs/story_mode_new.hpp; sourceTree = SOURCE_ROOT; };
95E5C3C0148C418100AD3FCC /* game_slot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = game_slot.cpp; path = ../../challenges/game_slot.cpp; sourceTree = SOURCE_ROOT; };
95E5C3C1148C418100AD3FCC /* game_slot.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = game_slot.hpp; path = ../../challenges/game_slot.hpp; sourceTree = SOURCE_ROOT; };
95E6A0BE11DCF37800AE088A /* addons_loading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = addons_loading.cpp; path = ../../states_screens/dialogs/addons_loading.cpp; sourceTree = SOURCE_ROOT; };
95E6A0BF11DCF37800AE088A /* addons_loading.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = addons_loading.hpp; path = ../../states_screens/dialogs/addons_loading.hpp; sourceTree = SOURCE_ROOT; };
95ECA0EC10124C5000D47C5F /* button_widget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = button_widget.cpp; path = ../../guiengine/widgets/button_widget.cpp; sourceTree = SOURCE_ROOT; };
@ -2416,6 +2419,8 @@
95C2AE270F296541000D3E5D /* challenge.hpp */,
95C2AE280F296541000D3E5D /* challenge_data.cpp */,
95C2AE290F296541000D3E5D /* challenge_data.hpp */,
95E5C3C0148C418100AD3FCC /* game_slot.cpp */,
95E5C3C1148C418100AD3FCC /* game_slot.hpp */,
95C2AE2A0F296541000D3E5D /* unlock_manager.cpp */,
95C2AE2B0F296541000D3E5D /* unlock_manager.hpp */,
);
@ -3195,6 +3200,7 @@
95AA4C67148AF2CC0053771D /* lod_node_loader.cpp in Sources */,
95E5C318148C17E500AD3FCC /* story_mode_lobby.cpp in Sources */,
95E5C335148C19F500AD3FCC /* story_mode_new.cpp in Sources */,
95E5C3C2148C418100AD3FCC /* game_slot.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -49,6 +49,8 @@ public:
}
void close();
bool is_open() { return m_base.is_open(); }
};
#endif

View File

@ -354,7 +354,7 @@ bool KartPropertiesManager::kartAvailable(int kartid)
if ( kartid == *it) return false;
}
const KartProperties *kartprop = getKartById(kartid);
if(unlock_manager->isLocked(kartprop->getIdent())) return false;
if(unlock_manager->getCurrentSlot()->isLocked(kartprop->getIdent())) return false;
return true;
} // kartAvailable
@ -463,7 +463,7 @@ void KartPropertiesManager::getRandomKartList(int count,
const KartProperties &kp=m_karts_properties[karts_in_group[i]];
if (!used[karts_in_group[i]] &&
m_kart_available[karts_in_group[i]] &&
!unlock_manager->isLocked(kp.getIdent()) )
!unlock_manager->getCurrentSlot()->isLocked(kp.getIdent()) )
{
random_kart_queue.push_back(kp.getIdent());
}

View File

@ -703,7 +703,7 @@ int handleCmdLine(int argc, char **argv)
}
else if( (!strcmp(argv[i], "--kart") && i+1<argc ))
{
if (!unlock_manager->isLocked(argv[i+1]))
if (!unlock_manager->getCurrentSlot()->isLocked(argv[i+1]))
{
const KartProperties *prop =
kart_properties_manager->getKart(argv[i+1]);
@ -764,7 +764,7 @@ int handleCmdLine(int argc, char **argv)
else if( (!strcmp(argv[i], "--track") || !strcmp(argv[i], "-t"))
&& i+1<argc )
{
if (!unlock_manager->isLocked(argv[i+1]))
if (!unlock_manager->getCurrentSlot()->isLocked(argv[i+1]))
{
race_manager->setTrack(argv[i+1]);
fprintf ( stdout, "You choose to start in track: %s.\n",
@ -829,7 +829,7 @@ int handleCmdLine(int argc, char **argv)
for (size_t i = 0; i != track_manager->getNumberOfTracks(); i++)
{
const Track *track = track_manager->getTrack(i);
if (!unlock_manager->isLocked(track->getIdent()))
if (!unlock_manager->getCurrentSlot()->isLocked(track->getIdent()))
{
fprintf ( stdout, "\t%14s: %ls\n",
track->getIdent().c_str(),
@ -847,7 +847,7 @@ int handleCmdLine(int argc, char **argv)
{
const KartProperties* KP =
kart_properties_manager->getKartById(i);
if (!unlock_manager->isLocked(KP->getIdent()))
if (!unlock_manager->getCurrentSlot()->isLocked(KP->getIdent()))
{
fprintf (stdout, "\t%10s: %ls\n", KP->getIdent().c_str(),
KP->getName());

View File

@ -332,7 +332,7 @@ void World::terminateRace()
updateHighscores(&best_highscore_rank, &best_finish_time, &highscore_who,
&best_player);
unlock_manager->raceFinished();
unlock_manager->getCurrentSlot()->raceFinished();
if (m_race_gui) m_race_gui->clearAllMessages();
// we can't delete the race gui here, since it is needed in case of

View File

@ -102,7 +102,7 @@ void RaceManager::setDefaultAIKartList(const std::vector<std::string>& ai_list)
name.c_str());
continue;
}
if(unlock_manager->isLocked(name))
if(unlock_manager->getCurrentSlot()->isLocked(name))
{
printf("Kart '%s' is locked and therefore ignored.\n",
name.c_str());
@ -489,7 +489,7 @@ void RaceManager::exitRace()
// were finished, and not when a race is aborted.
if (m_major_mode==MAJOR_MODE_GRAND_PRIX && m_track_number==(int)m_tracks.size())
{
unlock_manager->grandPrixFinished();
unlock_manager->getCurrentSlot()->grandPrixFinished();
StateManager::get()->resetAndGoToScreen( MainMenuScreen::getInstance() );

View File

@ -200,7 +200,7 @@ void ArenasScreen::buildTrackList()
Track* curr = track_manager->getTrack(n);
if (!curr->isArena()) continue;
if (unlock_manager->isLocked(curr->getIdent()))
if (unlock_manager->getCurrentSlot()->isLocked(curr->getIdent()))
{
w->addItem( _("Locked : solve active challenges to gain access to more!"),
"locked", curr->getScreenshotFile(), LOCKED_BADGE );
@ -223,7 +223,7 @@ void ArenasScreen::buildTrackList()
Track* curr = track_manager->getTrack(currArenas[n]);
if (!curr->isArena()) continue;
if (unlock_manager->isLocked(curr->getIdent()))
if (unlock_manager->getCurrentSlot()->isLocked(curr->getIdent()))
{
w->addItem( _("Locked : solve active challenges to gain access to more!"),
"locked", curr->getScreenshotFile(), LOCKED_BADGE );

View File

@ -69,9 +69,11 @@ void ChallengesScreen::beforeAddingWidget()
DynamicRibbonWidget* w = this->getWidget<DynamicRibbonWidget>("challenges");
assert( w != NULL );
const std::vector<const ChallengeData*>& activeChallenges = unlock_manager->getActiveChallenges();
const std::vector<const ChallengeData*>& solvedChallenges = unlock_manager->getUnlockedFeatures();
const std::vector<const ChallengeData*>& lockedChallenges = unlock_manager->getLockedChallenges();
GameSlot* slot = unlock_manager->getCurrentSlot();
const std::vector<const ChallengeData*>& activeChallenges = slot->getActiveChallenges();
const std::vector<const ChallengeData*>& solvedChallenges = slot->getUnlockedFeatures();
const std::vector<const ChallengeData*>& lockedChallenges = slot->getLockedChallenges();
const int activeChallengeAmount = activeChallenges.size();
const int solvedChallengeAmount = solvedChallenges.size();
@ -92,9 +94,11 @@ void ChallengesScreen::init()
// Re-build track list everytime (accounts for locking changes, etc.)
w->clearItems();
const std::vector<const ChallengeData*>& activeChallenges = unlock_manager->getActiveChallenges();
const std::vector<const ChallengeData*>& solvedChallenges = unlock_manager->getUnlockedFeatures();
const std::vector<const ChallengeData*>& lockedChallenges = unlock_manager->getLockedChallenges();
GameSlot* slot = unlock_manager->getCurrentSlot();
const std::vector<const ChallengeData*>& activeChallenges = slot->getActiveChallenges();
const std::vector<const ChallengeData*>& solvedChallenges = slot->getUnlockedFeatures();
const std::vector<const ChallengeData*>& lockedChallenges = slot->getLockedChallenges();
const int activeChallengeAmount = activeChallenges.size();
const int solvedChallengeAmount = solvedChallenges.size();
@ -158,7 +162,7 @@ void ChallengesScreen::eventCallback(GUIEngine::Widget* widget, const std::strin
UserConfigParams::m_default_kart.revertToDefaults();
}
const Challenge* c = unlock_manager->getChallenge(selection);
const ChallengeData* c = unlock_manager->getChallenge(selection);
if (c == NULL)
{
std::cerr << "[ChallengesScreen] ERROR: cannot find challenge '" << selection.c_str() << "'!\n";

View File

@ -309,7 +309,7 @@ RaceOverDialog::RaceOverDialog(const float percentWidth,
}
// ---- Buttons at the bottom
if (unlock_manager->getRecentlyUnlockedFeatures().size() > 0)
if (unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures().size() > 0)
{
const int label_y = m_area.getHeight() - (button_h + margin_between_buttons)*2;
@ -480,8 +480,8 @@ GUIEngine::EventPropagation RaceOverDialog::processEvent(const std::string& even
else if (eventSource == "seeunlocked")
{
std::vector<const ChallengeData*> unlocked =
unlock_manager->getRecentlyUnlockedFeatures();
unlock_manager->clearUnlocked();
unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures();
unlock_manager->getCurrentSlot()->clearUnlocked();
FeatureUnlockedCutScene* scene =
FeatureUnlockedCutScene::getInstance();
@ -505,7 +505,7 @@ GUIEngine::EventPropagation RaceOverDialog::processEvent(const std::string& even
void RaceOverDialog::escapePressed()
{
if (unlock_manager->getRecentlyUnlockedFeatures().size() > 0)
if (unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures().size() > 0)
{
std::string what = "seeunlocked";
processEvent(what);

View File

@ -50,6 +50,8 @@ StoryModeNewDialog::StoryModeNewDialog(const float w, const float h) :
RibbonWidget* difficulty = getWidget<RibbonWidget>("difficulty");
difficulty->setSelection( 1 /* medium */, PLAYER_ID_GAME_MASTER );
ident->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
}
// -----------------------------------------------------------------------------

View File

@ -504,7 +504,7 @@ void FeatureUnlockedCutScene::addUnlockedThings(const std::vector<const Challeng
{
for (unsigned int n=0; n<unlocked.size(); n++)
{
const std::vector<Challenge::UnlockableFeature>&
const std::vector<ChallengeData::UnlockableFeature>&
unlockedFeatures = unlocked[n]->getFeatures();
assert(unlockedFeatures.size() > 0);
@ -512,7 +512,7 @@ void FeatureUnlockedCutScene::addUnlockedThings(const std::vector<const Challeng
{
switch (unlockedFeatures[i].m_type)
{
case Challenge::UNLOCK_TRACK:
case ChallengeData::UNLOCK_TRACK:
{
Track* track =
track_manager->getTrack(unlockedFeatures[i].m_name);
@ -522,7 +522,7 @@ void FeatureUnlockedCutScene::addUnlockedThings(const std::vector<const Challeng
unlockedFeatures[i].getUnlockedMessage() );
break;
}
case Challenge::UNLOCK_GP:
case ChallengeData::UNLOCK_GP:
{
std::vector<ITexture*> images;
const GrandPrixData* gp =
@ -560,7 +560,7 @@ void FeatureUnlockedCutScene::addUnlockedThings(const std::vector<const Challeng
unlockedFeatures[i].getUnlockedMessage() );
break;
}
case Challenge::UNLOCK_MODE:
case ChallengeData::UNLOCK_MODE:
{
const RaceManager::MinorRaceModeType mode =
RaceManager::getModeIDFromInternalName(unlockedFeatures[i].m_name);
@ -569,7 +569,7 @@ void FeatureUnlockedCutScene::addUnlockedThings(const std::vector<const Challeng
unlockedFeatures[i].getUnlockedMessage() );
break;
}
case Challenge::UNLOCK_KART:
case ChallengeData::UNLOCK_KART:
{
const KartProperties* kart =
kart_properties_manager->getKart(unlockedFeatures[i].m_name);
@ -595,7 +595,7 @@ void FeatureUnlockedCutScene::addUnlockedThings(const std::vector<const Challeng
break;
}
case Challenge::UNLOCK_DIFFICULTY:
case ChallengeData::UNLOCK_DIFFICULTY:
{
//TODO : implement difficulty reward
std::cerr << "OK, I see you unlocked a difficulty, but this is not supported yet\n";

View File

@ -272,11 +272,11 @@ void GrandPrixLose::eventCallback(GUIEngine::Widget* widget,
// un-set the GP mode so that after unlocking, it doesn't try to continue the GP
race_manager->setMajorMode (RaceManager::MAJOR_MODE_SINGLE);
if (unlock_manager->getRecentlyUnlockedFeatures().size() > 0)
if (unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures().size() > 0)
{
std::vector<const ChallengeData*> unlocked =
unlock_manager->getRecentlyUnlockedFeatures();
unlock_manager->clearUnlocked();
unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures();
unlock_manager->getCurrentSlot()->clearUnlocked();
FeatureUnlockedCutScene* scene =
FeatureUnlockedCutScene::getInstance();

View File

@ -96,7 +96,7 @@ void GrandPrixWin::loadedFromFile()
void GrandPrixWin::init()
{
Screen::init();
if (unlock_manager->getRecentlyUnlockedFeatures().size() > 0)
if (unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures().size() > 0)
{
const core::dimension2d<u32>& frame_size = GUIEngine::getDriver()->getCurrentRenderTargetSize();
@ -394,11 +394,11 @@ void GrandPrixWin::eventCallback(GUIEngine::Widget* widget,
// un-set the GP mode so that after unlocking, it doesn't try to continue the GP
race_manager->setMajorMode (RaceManager::MAJOR_MODE_SINGLE);
if (unlock_manager->getRecentlyUnlockedFeatures().size() > 0)
if (unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures().size() > 0)
{
std::vector<const ChallengeData*> unlocked =
unlock_manager->getRecentlyUnlockedFeatures();
unlock_manager->clearUnlocked();
unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures();
unlock_manager->getCurrentSlot()->clearUnlocked();
FeatureUnlockedCutScene* scene =
FeatureUnlockedCutScene::getInstance();

View File

@ -1962,7 +1962,7 @@ void KartSelectionScreen::setKartsFromCurrentGroup()
{
const KartProperties* prop =
kart_properties_manager->getKartById(n);
if (unlock_manager->isLocked(prop->getIdent()))
if (unlock_manager->getCurrentSlot()->isLocked(prop->getIdent()))
{
w->addItem(
_("Locked : solve active challenges to gain access "
@ -1993,7 +1993,7 @@ void KartSelectionScreen::setKartsFromCurrentGroup()
kart_properties_manager->getKartById(group[n]);
const std::string &icon_path = prop->getAbsoluteIconFile();
if (unlock_manager->isLocked(prop->getIdent()))
if (unlock_manager->getCurrentSlot()->isLocked(prop->getIdent()))
{
w->addItem(
_("Locked : solve active challenges to gain access "

View File

@ -91,7 +91,7 @@ void RaceResultGUI::enableAllButtons()
// If something was unlocked
// -------------------------
int n = unlock_manager->getRecentlyUnlockedFeatures().size();
int n = unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures().size();
if(n>0)
{
top->setText(n==1 ? _("See unlocked feature")
@ -138,7 +138,7 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
// If something was unlocked, the 'continue' button was
// actually used to display "Show unlocked feature(s)" text.
// ---------------------------------------------------------
int n = unlock_manager->getRecentlyUnlockedFeatures().size();
int n = unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures().size();
if(n>0)
{
if(name=="top")
@ -149,8 +149,8 @@ void RaceResultGUI::eventCallback(GUIEngine::Widget* widget,
}
std::vector<const ChallengeData*> unlocked =
unlock_manager->getRecentlyUnlockedFeatures();
unlock_manager->clearUnlocked();
unlock_manager->getCurrentSlot()->getRecentlyUnlockedFeatures();
unlock_manager->getCurrentSlot()->clearUnlocked();
FeatureUnlockedCutScene* scene =
FeatureUnlockedCutScene::getInstance();
scene->addUnlockedThings(unlocked);

View File

@ -205,7 +205,7 @@ void RaceSetupScreen::init()
name2 += _("Contains no powerups, so only your driving skills matter!");
w2->addItem( name2, IDENT_TTRIAL, RaceManager::getIconOf(RaceManager::MINOR_MODE_TIME_TRIAL));
if (unlock_manager->isLocked(IDENT_FTL))
if (unlock_manager->getCurrentSlot()->isLocked(IDENT_FTL))
{
w2->addItem( _("Locked : solve active challenges to gain access to more!"),
"locked", RaceManager::getIconOf(RaceManager::MINOR_MODE_FOLLOW_LEADER), true);

View File

@ -247,7 +247,7 @@ void TracksScreen::init()
sshot_files.push_back("gui/main_help.png");
}
if (unlock_manager->isLocked(gp->getId()))
if (unlock_manager->getCurrentSlot()->isLocked(gp->getId()))
{
gps_widget->addAnimatedItem(_("Locked!"),
"locked", sshot_files, 1.5f, LOCKED_BADGE | TROPHY_BADGE,
@ -304,7 +304,7 @@ void TracksScreen::buildTrackList()
Track* curr = track_manager->getTrack( n );
if (curr->isArena()) continue;
if (unlock_manager->isLocked(curr->getIdent()))
if (unlock_manager->getCurrentSlot()->isLocked(curr->getIdent()))
{
tracks_widget->addItem( _("Locked : solve active challenges to gain access to more!"),
"locked", curr->getScreenshotFile(), LOCKED_BADGE,
@ -329,7 +329,7 @@ void TracksScreen::buildTrackList()
Track* curr = track_manager->getTrack( curr_group[n] );
if (curr->isArena()) continue;
if (unlock_manager->isLocked(curr->getIdent()))
if (unlock_manager->getCurrentSlot()->isLocked(curr->getIdent()))
{
tracks_widget->addItem( _("Locked : solve active challenges to gain access to more!"),
"locked", curr->getScreenshotFile(), LOCKED_BADGE,