Add support for using ghost kart in challenge
Real challenge file added later.
This commit is contained in:
parent
33defa44b7
commit
11b119066c
@ -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]);
|
||||||
|
@ -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; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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,113 +68,135 @@ 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;
|
|
||||||
ReplayData rd;
|
|
||||||
|
|
||||||
rd.m_filename = *i;
|
|
||||||
|
|
||||||
fgets(s, 1023, fd);
|
|
||||||
unsigned int version;
|
|
||||||
if (sscanf(s,"version: %u", &version) != 1)
|
|
||||||
{
|
{
|
||||||
Log::warn("Replay", "No Version information "
|
// Skip invalid replay file
|
||||||
"found in replay file (bogus replay file).");
|
|
||||||
fclose(fd);
|
|
||||||
continue;
|
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
|
} // 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()
|
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.",
|
||||||
|
@ -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); }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -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 (label.size() > 0) label.append(L"\n");
|
if (!c->isGhostReplay())
|
||||||
label.append(_("Number of AI Karts: %i", c->getNumKarts(difficulty) - 1));
|
{
|
||||||
|
if (label.size() > 0) label.append(L"\n");
|
||||||
|
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 );
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user