Add support for using ghost kart in challenge

Real challenge file added later.
This commit is contained in:
Benau 2016-03-23 14:26:48 +08:00
parent 33defa44b7
commit 11b119066c
7 changed files with 158 additions and 98 deletions

View File

@ -21,6 +21,7 @@
#include <sstream>
#include "challenges/unlock_manager.hpp"
#include "io/file_manager.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp"
@ -28,6 +29,7 @@
#include "race/grand_prix_data.hpp"
#include "race/grand_prix_manager.hpp"
#include "race/race_manager.hpp"
#include "replay/replay_play.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
@ -41,6 +43,7 @@ ChallengeData::ChallengeData(const std::string& filename)
m_gp_id = "";
m_version = 0;
m_num_trophies = 0;
m_is_ghost_replay = false;
for (int d=0; d<RaceManager::DIFFICULTY_COUNT; d++)
{
@ -175,6 +178,13 @@ ChallengeData::ChallengeData(const std::string& filename)
if (!karts_node->get("number", &num_karts)) error("karts");
m_num_karts[d] = num_karts;
std::string replay_file;
if (karts_node->get("replay_file", &replay_file))
{
m_is_ghost_replay = true;
m_replay_files[d] = replay_file;
}
std::string ai_kart_ident;
if (karts_node->get("aiIdent", &ai_kart_ident))
m_ai_kart_ident[d] = ai_kart_ident;
@ -387,6 +397,16 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const
race_manager->setNumPlayers(1);
}
if (m_is_ghost_replay)
{
const bool result = ReplayPlay::get()->addReplayFile(file_manager
->getAsset(FileManager::CHALLENGE, m_replay_files[d]),
true/*custom_replay*/);
if (!result)
Log::fatal("ChallengeData", "Can't open replay for challenge!");
race_manager->setRaceGhostKarts(true);
}
if (m_ai_kart_ident[d] != "")
{
race_manager->setAIKartOverride(m_ai_kart_ident[d]);

View File

@ -86,6 +86,7 @@ private:
int m_position[RaceManager::DIFFICULTY_COUNT];
int m_num_karts[RaceManager::DIFFICULTY_COUNT];
std::string m_ai_kart_ident[RaceManager::DIFFICULTY_COUNT];
std::string m_replay_files[RaceManager::DIFFICULTY_COUNT];
float m_time[RaceManager::DIFFICULTY_COUNT];
int m_energy[RaceManager::DIFFICULTY_COUNT];
RaceManager::AISuperPower m_ai_superpower[RaceManager::DIFFICULTY_COUNT];
@ -94,6 +95,7 @@ private:
std::string m_filename;
/** Version number of the challenge. */
int m_version;
bool m_is_ghost_replay;
void setUnlocks(const std::string &id,
ChallengeData::RewardType reward);
@ -182,6 +184,9 @@ public:
/** Returns if this challenge is a grand prix. */
bool isSingleRace() const { return m_mode == CM_SINGLE_RACE; }
// ------------------------------------------------------------------------
/** Returns if this challenge is using ghost replay. */
bool isGhostReplay() const { return m_is_ghost_replay; }
// ------------------------------------------------------------------------
/** Returns the challenge mode of this challenge. */
ChallengeModeType getMode() const { return m_mode; }
// ------------------------------------------------------------------------

View File

@ -26,12 +26,14 @@ ReplayBase::ReplayBase()
// -----------------------------------------------------------------------------
/** Opens a replay file which is determined by sub classes.
* \param writeable True if the file should be opened for writing.
* \param full_path True if the file is full path.
* \return A FILE *, or NULL if the file could not be opened.
*/
FILE* ReplayBase::openReplayFile(bool writeable)
FILE* ReplayBase::openReplayFile(bool writeable, bool full_path)
{
FILE *fd = fopen((file_manager->getReplayDir() +
getReplayFilename()).c_str(), writeable ? "w" : "r");
FILE *fd = fopen(full_path ? getReplayFilename().c_str() :
(file_manager->getReplayDir() + getReplayFilename()).c_str(),
writeable ? "w" : "r");
if (!fd)
{
return NULL;

View File

@ -68,7 +68,7 @@ protected:
}; // KartReplayEvent
// ------------------------------------------------------------------------
FILE *openReplayFile(bool writeable);
FILE *openReplayFile(bool writeable, bool full_path = false);
// ------------------------------------------------------------------------
/** Returns the filename that was opened. */
virtual const std::string& getReplayFilename() const = 0;

View File

@ -40,6 +40,7 @@ ReplayPlay *ReplayPlay::m_replay_play = NULL;
ReplayPlay::ReplayPlay()
{
m_current_replay_file = 0;
m_custom_replay_file = false;
} // ReplayPlay
//-----------------------------------------------------------------------------
@ -67,113 +68,135 @@ void ReplayPlay::loadAllReplayFile()
file_manager->listFiles(files, file_manager->getReplayDir(),
/*is_full_path*/ false);
char s[1024], s1[1024];
for (std::set<std::string>::iterator i = files.begin();
i != files.end(); ++i)
{
if (StringUtils::getExtension(*i) != "replay") continue;
FILE *fd = fopen((file_manager->getReplayDir() + (*i)).c_str(), "r");
if (fd == NULL) continue;
ReplayData rd;
rd.m_filename = *i;
fgets(s, 1023, fd);
unsigned int version;
if (sscanf(s,"version: %u", &version) != 1)
if (!addReplayFile(*i))
{
Log::warn("Replay", "No Version information "
"found in replay file (bogus replay file).");
fclose(fd);
// Skip invalid replay file
continue;
}
if (version != getReplayVersion())
{
Log::warn("Replay", "Replay is version '%d'", version);
Log::warn("Replay", "STK version is '%d'", getReplayVersion());
Log::warn("Replay", "Skipped '%s'", i->c_str());
fclose(fd);
continue;
}
while(true)
{
fgets(s, 1023, fd);
core::stringc is_end(s);
is_end.trim();
if (is_end == "kart_list_end") break;
char s1[1024];
if (sscanf(s,"kart: %s", s1) != 1)
{
Log::warn("Replay", "Could not read ghost karts info!");
break;
}
rd.m_kart_list.push_back(std::string(s1));
}
int reverse = 0;
fgets(s, 1023, fd);
if(sscanf(s, "reverse: %d", &reverse) != 1)
{
Log::warn("Replay", "Reverse info found in replay file.");
fclose(fd);
continue;
}
rd.m_reverse = reverse!=0;
fgets(s, 1023, fd);
if (sscanf(s, "difficulty: %u", &rd.m_difficulty) != 1)
{
Log::warn("Replay", " No difficulty found in replay file.");
fclose(fd);
continue;
}
fgets(s, 1023, fd);
if (sscanf(s, "track: %s", s1) != 1)
{
Log::warn("Replay", "Track info not found in replay file.");
fclose(fd);
continue;
}
rd.m_track_name = std::string(s1);
Track* t = track_manager->getTrack(rd.m_track_name);
if (t == NULL)
{
Log::warn("Replay", "Track '%s' used in replay not found in STK!",
rd.m_track_name.c_str());
fclose(fd);
continue;
}
fgets(s, 1023, fd);
if (sscanf(s, "laps: %u", &rd.m_laps) != 1)
{
Log::warn("Replay", "No number of laps found in replay file.");
fclose(fd);
continue;
}
fgets(s, 1023, fd);
if (sscanf(s, "min_time: %f", &rd.m_min_time) != 1)
{
Log::warn("Replay", "Finish time not found in replay file.");
fclose(fd);
continue;
}
fclose(fd);
m_replay_file_list.push_back(rd);
}
} // loadAllReplayFile
//-----------------------------------------------------------------------------
bool ReplayPlay::addReplayFile(const std::string& fn, bool custom_replay)
{
// custom_replay is true when full path of filename is given
m_custom_replay_file = custom_replay;
char s[1024], s1[1024];
if (StringUtils::getExtension(fn) != "replay") return false;
FILE *fd = fopen(custom_replay ? fn.c_str() :
(file_manager->getReplayDir() + fn).c_str(), "r");
if (fd == NULL) return false;
ReplayData rd;
rd.m_filename = fn;
fgets(s, 1023, fd);
unsigned int version;
if (sscanf(s,"version: %u", &version) != 1)
{
Log::warn("Replay", "No Version information "
"found in replay file (bogus replay file).");
fclose(fd);
return false;
}
if (version != getReplayVersion())
{
Log::warn("Replay", "Replay is version '%d'", version);
Log::warn("Replay", "STK version is '%d'", getReplayVersion());
Log::warn("Replay", "Skipped '%s'", fn.c_str());
fclose(fd);
return false;
}
while(true)
{
fgets(s, 1023, fd);
core::stringc is_end(s);
is_end.trim();
if (is_end == "kart_list_end") break;
char s1[1024];
if (sscanf(s,"kart: %s", s1) != 1)
{
Log::warn("Replay", "Could not read ghost karts info!");
break;
}
rd.m_kart_list.push_back(std::string(s1));
}
int reverse = 0;
fgets(s, 1023, fd);
if(sscanf(s, "reverse: %d", &reverse) != 1)
{
Log::warn("Replay", "Reverse info found in replay file.");
fclose(fd);
return false;
}
rd.m_reverse = reverse != 0;
fgets(s, 1023, fd);
if (sscanf(s, "difficulty: %u", &rd.m_difficulty) != 1)
{
Log::warn("Replay", " No difficulty found in replay file.");
fclose(fd);
return false;
}
fgets(s, 1023, fd);
if (sscanf(s, "track: %s", s1) != 1)
{
Log::warn("Replay", "Track info not found in replay file.");
fclose(fd);
return false;
}
rd.m_track_name = std::string(s1);
Track* t = track_manager->getTrack(rd.m_track_name);
if (t == NULL)
{
Log::warn("Replay", "Track '%s' used in replay not found in STK!",
rd.m_track_name.c_str());
fclose(fd);
return false;
}
fgets(s, 1023, fd);
if (sscanf(s, "laps: %u", &rd.m_laps) != 1)
{
Log::warn("Replay", "No number of laps found in replay file.");
fclose(fd);
return false;
}
fgets(s, 1023, fd);
if (sscanf(s, "min_time: %f", &rd.m_min_time) != 1)
{
Log::warn("Replay", "Finish time not found in replay file.");
fclose(fd);
return false;
}
fclose(fd);
m_replay_file_list.push_back(rd);
assert(m_replay_file_list.size() > 0);
// Force to use custom replay file immediately
if (custom_replay)
m_current_replay_file = m_replay_file_list.size() - 1;
return true;
} // addReplayFile
//-----------------------------------------------------------------------------
void ReplayPlay::load()
{
m_ghost_karts.clearAndDeleteAll();
char s[1024];
FILE *fd = openReplayFile(/*writeable*/false);
FILE *fd = openReplayFile(/*writeable*/false, m_custom_replay_file);
if(!fd)
{
Log::error("Replay", "Can't read '%s', ghost replay disabled.",

View File

@ -93,6 +93,8 @@ private:
unsigned int m_current_replay_file;
bool m_custom_replay_file;
std::vector<ReplayData> m_replay_file_list;
/** All ghost karts. */
@ -118,6 +120,9 @@ public:
void setReplayFile(unsigned int n)
{ m_current_replay_file = n; }
// ------------------------------------------------------------------------
bool addReplayFile(const std::string& fn,
bool custom_replay = false);
// ------------------------------------------------------------------------
const ReplayData& getReplayData(unsigned int n) const
{ return m_replay_file_list.at(n); }
// ------------------------------------------------------------------------

View File

@ -63,8 +63,11 @@ core::stringw getLabel(RaceManager::Difficulty difficulty, const ChallengeData*
label.append( _("Required Nitro Points: %i", c->getEnergy(difficulty)) );
}
if (label.size() > 0) label.append(L"\n");
label.append(_("Number of AI Karts: %i", c->getNumKarts(difficulty) - 1));
if (!c->isGhostReplay())
{
if (label.size() > 0) label.append(L"\n");
label.append(_("Number of AI Karts: %i", c->getNumKarts(difficulty) - 1));
}
return label;
}
@ -144,6 +147,8 @@ SelectChallengeDialog::SelectChallengeDialog(const float percentWidth,
typeLbl->setText(_("Grand Prix"), false );
else if (c->getData()->getEnergy(RaceManager::DIFFICULTY_EASY) > 0)
typeLbl->setText(_("Nitro challenge"), false );
else if (c->getData()->isGhostReplay())
typeLbl->setText(_("Ghost replay race"), false );
else
typeLbl->setText( RaceManager::getNameOf(c->getData()->getMinorMode()), false );