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 <sstream>
#include "challenges/unlock_manager.hpp" #include "challenges/unlock_manager.hpp"
#include "io/file_manager.hpp"
#include "karts/abstract_kart.hpp" #include "karts/abstract_kart.hpp"
#include "karts/kart_properties.hpp" #include "karts/kart_properties.hpp"
#include "karts/kart_properties_manager.hpp" #include "karts/kart_properties_manager.hpp"
@ -28,6 +29,7 @@
#include "race/grand_prix_data.hpp" #include "race/grand_prix_data.hpp"
#include "race/grand_prix_manager.hpp" #include "race/grand_prix_manager.hpp"
#include "race/race_manager.hpp" #include "race/race_manager.hpp"
#include "replay/replay_play.hpp"
#include "tracks/track.hpp" #include "tracks/track.hpp"
#include "tracks/track_manager.hpp" #include "tracks/track_manager.hpp"
@ -41,6 +43,7 @@ ChallengeData::ChallengeData(const std::string& filename)
m_gp_id = ""; m_gp_id = "";
m_version = 0; m_version = 0;
m_num_trophies = 0; m_num_trophies = 0;
m_is_ghost_replay = false;
for (int d=0; d<RaceManager::DIFFICULTY_COUNT; d++) 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"); if (!karts_node->get("number", &num_karts)) error("karts");
m_num_karts[d] = num_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; std::string ai_kart_ident;
if (karts_node->get("aiIdent", &ai_kart_ident)) if (karts_node->get("aiIdent", &ai_kart_ident))
m_ai_kart_ident[d] = 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); 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] != "") if (m_ai_kart_ident[d] != "")
{ {
race_manager->setAIKartOverride(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_position[RaceManager::DIFFICULTY_COUNT];
int m_num_karts[RaceManager::DIFFICULTY_COUNT]; int m_num_karts[RaceManager::DIFFICULTY_COUNT];
std::string m_ai_kart_ident[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]; float m_time[RaceManager::DIFFICULTY_COUNT];
int m_energy[RaceManager::DIFFICULTY_COUNT]; int m_energy[RaceManager::DIFFICULTY_COUNT];
RaceManager::AISuperPower m_ai_superpower[RaceManager::DIFFICULTY_COUNT]; RaceManager::AISuperPower m_ai_superpower[RaceManager::DIFFICULTY_COUNT];
@ -94,6 +95,7 @@ private:
std::string m_filename; std::string m_filename;
/** Version number of the challenge. */ /** Version number of the challenge. */
int m_version; int m_version;
bool m_is_ghost_replay;
void setUnlocks(const std::string &id, void setUnlocks(const std::string &id,
ChallengeData::RewardType reward); ChallengeData::RewardType reward);
@ -182,6 +184,9 @@ public:
/** Returns if this challenge is a grand prix. */ /** Returns if this challenge is a grand prix. */
bool isSingleRace() const { return m_mode == CM_SINGLE_RACE; } 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. */ /** Returns the challenge mode of this challenge. */
ChallengeModeType getMode() const { return m_mode; } ChallengeModeType getMode() const { return m_mode; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -26,12 +26,14 @@ ReplayBase::ReplayBase()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/** Opens a replay file which is determined by sub classes. /** Opens a replay file which is determined by sub classes.
* \param writeable True if the file should be opened for writing. * \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. * \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() + FILE *fd = fopen(full_path ? getReplayFilename().c_str() :
getReplayFilename()).c_str(), writeable ? "w" : "r"); (file_manager->getReplayDir() + getReplayFilename()).c_str(),
writeable ? "w" : "r");
if (!fd) if (!fd)
{ {
return NULL; return NULL;

View File

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

View File

@ -40,6 +40,7 @@ ReplayPlay *ReplayPlay::m_replay_play = NULL;
ReplayPlay::ReplayPlay() ReplayPlay::ReplayPlay()
{ {
m_current_replay_file = 0; m_current_replay_file = 0;
m_custom_replay_file = false;
} // ReplayPlay } // ReplayPlay
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -67,16 +68,31 @@ void ReplayPlay::loadAllReplayFile()
file_manager->listFiles(files, file_manager->getReplayDir(), file_manager->listFiles(files, file_manager->getReplayDir(),
/*is_full_path*/ false); /*is_full_path*/ false);
char s[1024], s1[1024];
for (std::set<std::string>::iterator i = files.begin(); for (std::set<std::string>::iterator i = files.begin();
i != files.end(); ++i) i != files.end(); ++i)
{ {
if (StringUtils::getExtension(*i) != "replay") continue; if (!addReplayFile(*i))
FILE *fd = fopen((file_manager->getReplayDir() + (*i)).c_str(), "r"); {
if (fd == NULL) continue; // Skip invalid replay file
continue;
}
}
} // 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; ReplayData rd;
rd.m_filename = *i; rd.m_filename = fn;
fgets(s, 1023, fd); fgets(s, 1023, fd);
unsigned int version; unsigned int version;
@ -85,15 +101,15 @@ void ReplayPlay::loadAllReplayFile()
Log::warn("Replay", "No Version information " Log::warn("Replay", "No Version information "
"found in replay file (bogus replay file)."); "found in replay file (bogus replay file).");
fclose(fd); fclose(fd);
continue; return false;
} }
if (version != getReplayVersion()) if (version != getReplayVersion())
{ {
Log::warn("Replay", "Replay is version '%d'", version); Log::warn("Replay", "Replay is version '%d'", version);
Log::warn("Replay", "STK version is '%d'", getReplayVersion()); Log::warn("Replay", "STK version is '%d'", getReplayVersion());
Log::warn("Replay", "Skipped '%s'", i->c_str()); Log::warn("Replay", "Skipped '%s'", fn.c_str());
fclose(fd); fclose(fd);
continue; return false;
} }
while(true) while(true)
@ -118,7 +134,7 @@ void ReplayPlay::loadAllReplayFile()
{ {
Log::warn("Replay", "Reverse info found in replay file."); Log::warn("Replay", "Reverse info found in replay file.");
fclose(fd); fclose(fd);
continue; return false;
} }
rd.m_reverse = reverse != 0; rd.m_reverse = reverse != 0;
@ -127,7 +143,7 @@ void ReplayPlay::loadAllReplayFile()
{ {
Log::warn("Replay", " No difficulty found in replay file."); Log::warn("Replay", " No difficulty found in replay file.");
fclose(fd); fclose(fd);
continue; return false;
} }
fgets(s, 1023, fd); fgets(s, 1023, fd);
@ -135,7 +151,7 @@ void ReplayPlay::loadAllReplayFile()
{ {
Log::warn("Replay", "Track info not found in replay file."); Log::warn("Replay", "Track info not found in replay file.");
fclose(fd); fclose(fd);
continue; return false;
} }
rd.m_track_name = std::string(s1); rd.m_track_name = std::string(s1);
Track* t = track_manager->getTrack(rd.m_track_name); Track* t = track_manager->getTrack(rd.m_track_name);
@ -144,7 +160,7 @@ void ReplayPlay::loadAllReplayFile()
Log::warn("Replay", "Track '%s' used in replay not found in STK!", Log::warn("Replay", "Track '%s' used in replay not found in STK!",
rd.m_track_name.c_str()); rd.m_track_name.c_str());
fclose(fd); fclose(fd);
continue; return false;
} }
fgets(s, 1023, fd); fgets(s, 1023, fd);
@ -152,7 +168,7 @@ void ReplayPlay::loadAllReplayFile()
{ {
Log::warn("Replay", "No number of laps found in replay file."); Log::warn("Replay", "No number of laps found in replay file.");
fclose(fd); fclose(fd);
continue; return false;
} }
fgets(s, 1023, fd); fgets(s, 1023, fd);
@ -160,12 +176,19 @@ void ReplayPlay::loadAllReplayFile()
{ {
Log::warn("Replay", "Finish time not found in replay file."); Log::warn("Replay", "Finish time not found in replay file.");
fclose(fd); fclose(fd);
continue; return false;
} }
fclose(fd); fclose(fd);
m_replay_file_list.push_back(rd); m_replay_file_list.push_back(rd);
}
} // loadAllReplayFile 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() void ReplayPlay::load()
@ -173,7 +196,7 @@ void ReplayPlay::load()
m_ghost_karts.clearAndDeleteAll(); m_ghost_karts.clearAndDeleteAll();
char s[1024]; char s[1024];
FILE *fd = openReplayFile(/*writeable*/false); FILE *fd = openReplayFile(/*writeable*/false, m_custom_replay_file);
if(!fd) if(!fd)
{ {
Log::error("Replay", "Can't read '%s', ghost replay disabled.", Log::error("Replay", "Can't read '%s', ghost replay disabled.",

View File

@ -93,6 +93,8 @@ private:
unsigned int m_current_replay_file; unsigned int m_current_replay_file;
bool m_custom_replay_file;
std::vector<ReplayData> m_replay_file_list; std::vector<ReplayData> m_replay_file_list;
/** All ghost karts. */ /** All ghost karts. */
@ -118,6 +120,9 @@ public:
void setReplayFile(unsigned int n) void setReplayFile(unsigned int n)
{ m_current_replay_file = n; } { m_current_replay_file = n; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
bool addReplayFile(const std::string& fn,
bool custom_replay = false);
// ------------------------------------------------------------------------
const ReplayData& getReplayData(unsigned int n) const const ReplayData& getReplayData(unsigned int n) const
{ return m_replay_file_list.at(n); } { 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)) ); label.append( _("Required Nitro Points: %i", c->getEnergy(difficulty)) );
} }
if (!c->isGhostReplay())
{
if (label.size() > 0) label.append(L"\n"); if (label.size() > 0) label.append(L"\n");
label.append(_("Number of AI Karts: %i", c->getNumKarts(difficulty) - 1)); label.append(_("Number of AI Karts: %i", c->getNumKarts(difficulty) - 1));
}
return label; return label;
} }
@ -144,6 +147,8 @@ SelectChallengeDialog::SelectChallengeDialog(const float percentWidth,
typeLbl->setText(_("Grand Prix"), false ); typeLbl->setText(_("Grand Prix"), false );
else if (c->getData()->getEnergy(RaceManager::DIFFICULTY_EASY) > 0) else if (c->getData()->getEnergy(RaceManager::DIFFICULTY_EASY) > 0)
typeLbl->setText(_("Nitro challenge"), false ); typeLbl->setText(_("Nitro challenge"), false );
else if (c->getData()->isGhostReplay())
typeLbl->setText(_("Ghost replay race"), false );
else else
typeLbl->setText( RaceManager::getNameOf(c->getData()->getMinorMode()), false ); typeLbl->setText( RaceManager::getNameOf(c->getData()->getMinorMode()), false );