stk-code_catmod/src/race/grand_prix_data.cpp

196 lines
6.7 KiB
C++
Raw Normal View History

//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004-2013 Ingo Ruhnke <grumbel@gmx.de>
// Copyright (C) 2006-2013 Joerg Henrichs
//
// 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 "race/grand_prix_data.hpp"
#include "config/player_profile.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
#include "io/file_manager.hpp"
#include "tracks/track_manager.hpp"
#include "tracks/track.hpp"
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
#include <iostream>
#include <stdexcept>
GrandPrixData::GrandPrixData(const std::string filename) throw(std::logic_error)
{
m_filename = filename;
m_id = StringUtils::getBasename(StringUtils::removeExtension(filename));
XMLNode* root = file_manager->createXMLTree(file_manager->getAsset(FileManager::GRANDPRIX,filename));
if (!root)
{
Log::error("GrandPrixData","Error while trying to read grandprix file '%s'",
filename.c_str());
throw std::logic_error("File not found");
}
bool foundName = false;
if (root->getName() == "supertuxkart_grand_prix")
{
std::string temp_name;
if (root->get("name", &temp_name) == 0)
{
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
"missing 'name' attribute\n", filename.c_str());
delete root;
throw std::logic_error("File contents are incomplete or corrupt");
}
m_name = temp_name.c_str();
foundName = true;
}
else
{
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
"Root node has an unexpected name\n", filename.c_str());
delete root;
throw std::logic_error("File contents are incomplete or corrupt");
}
const int amount = root->getNumNodes();
for (int i=0; i<amount; i++)
{
const XMLNode* node = root->getNode(i);
// read a track entry
if (node->getName() == "track")
{
std::string trackID;
int numLaps;
bool reversed = false;
const int idFound = node->get("id", &trackID );
const int lapFound = node->get("laps", &numLaps );
// Will stay false if not found
node->get("reverse", &reversed );
if (!idFound || !lapFound)
{
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
"<track> tag does not have idi and laps reverse attributes. \n",
filename.c_str());
delete root;
throw std::logic_error("File contents are incomplete or corrupt");
}
// Make sure the track really is reversible
Track* t = track_manager->getTrack(trackID);
if (t != NULL && reversed)
{
reversed = t->reverseAvailable();
}
m_tracks.push_back(trackID);
m_laps.push_back(numLaps);
m_reversed.push_back(reversed);
assert(m_tracks.size() == m_laps.size() );
assert(m_laps.size() == m_reversed.size());
}
else
{
std::cerr << "Unknown node in Grand Prix XML file : " << node->getName().c_str() << std::endl;
delete root;
throw std::runtime_error("Unknown node in sfx XML file");
}
}// nend for
delete root;
// sanity checks
if (!foundName)
{
Log::error("GrandPrixData", "Error while trying to read grandprix file '%s' : "
"missing 'name' attribute\n", filename.c_str());
throw std::logic_error("File contents are incomplete or corrupt");
}
}
// ----------------------------------------------------------------------------
bool GrandPrixData::checkConsistency(bool chatty) const
{
for(unsigned int i=0; i<m_tracks.size(); i++)
{
Track* t = track_manager->getTrack(m_tracks[i]);
if (t == NULL)
{
if (chatty)
{
Log::error("GrandPrixData", "Grand Prix '%ls': Track '%s' does not exist!\n",
m_name.c_str(), m_tracks[i].c_str());
Log::error("GrandPrixData", "This Grand Prix will not be available.\n");
}
return false;
}
} // for i
return true;
} // checkConsistency
// ----------------------------------------------------------------------------
/** Returns true if the track is available. This is used to test if Fort Magma
* is available (this way FortMagma is not used in the last Grand Prix in
* story mode, but will be available once all challenges are done and nolok
* is unlocked).
*/
bool GrandPrixData::isTrackAvailable(const std::string &id) const
{
return id!="fortmagma" ||
!PlayerManager::get()->getCurrentPlayer()->isLocked("fortmagma");
} // isTrackAvailable
// ----------------------------------------------------------------------------
void GrandPrixData::getLaps(std::vector<int> *laps) const
{
laps->clear();
for(unsigned int i=0; i< m_tracks.size(); i++)
if(isTrackAvailable(m_tracks[i]))
laps->push_back(m_laps[i]);
} // getLaps
// ----------------------------------------------------------------------------
void GrandPrixData::getReverse(std::vector<bool> *reverse) const
{
reverse->clear();
for(unsigned int i=0; i< m_tracks.size(); i++)
if(isTrackAvailable(m_tracks[i]))
reverse->push_back(m_reversed[i]);
} // getReverse
// ----------------------------------------------------------------------------
const std::vector<std::string>& GrandPrixData::getTrackNames() const
{
m_really_available_tracks.clear();
for(unsigned int i=0; i< m_tracks.size(); i++)
{
if(isTrackAvailable(m_tracks[i]))
m_really_available_tracks.push_back(m_tracks[i]);
} // for i
return m_really_available_tracks;
} // getTrackNames
/* EOF */