Allow auto-save replay when specified in time trial mode.

It will disable AI when recording, also it will only save if the
race is completed, ie no one gave up or all events fit in max frame recorded.
This commit is contained in:
Benau
2016-02-11 00:42:33 +08:00
parent 5a9fdd7a8d
commit bb88a0f0ec
14 changed files with 91 additions and 40 deletions

View File

@@ -3,9 +3,9 @@
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
<div x="2%" y="2%" width="96%" height="96%" layout="vertical-row">
<header id="name" height="5%" width="80%" align="center" text_align="center"/>
<header id="name" height="7%" width="80%" align="center" text_align="center"/>
<spacer width="1" height="5%"/>
<spacer width="1" height="1%"/>
<box width="100%" height="40%" padding="10" layout="horizontal-row">
<!-- Left pane -->
@@ -49,8 +49,8 @@
</div>
</box>
<spacer width="1" height="5%"/>
<box width="100%" height="25%" padding="15" layout="vertical-row">
<spacer width="1" height="1%"/>
<box width="100%" height="33%" padding="15" layout="vertical-row">
<div width="100%" height="fit" layout="horizontal-row" >
<label id="lap-text" proportion="1" I18N="In the track info screen" text="Number of laps" text_align="right"/>
<spacer width="40"/>
@@ -78,9 +78,18 @@
</div>
</div>
</div>
<spacer width="1" height="2%"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label id="record-race-text" proportion="1" I18N="In the track info screen" text="Record the race for ghost replay" text_align="right"/>
<spacer width="40"/>
<div proportion="1" height="fit" layout="horizontal-row">
<div width="50%" height="fit" text-align="center" layout="vertical-row" >
<checkbox id="record" align="center"/>
</div>
</div>
</div>
<spacer width="1" height="1%"/>
</box>
<spacer width="1" height="5%"/>
<spacer width="1" height="1%"/>
<buttonbar id="buttons" height="15%" width="100%" align="center">
<icon-button id="start" width="64" height="64" icon="gui/green_check.png"
I18N="In the track info screen" text="Start Race"/>

View File

@@ -368,7 +368,7 @@ void InputManager::handleStaticAction(int key, int value)
if(world && value)
{
if(control_is_pressed && ReplayRecorder::get())
ReplayRecorder::get()->Save();
ReplayRecorder::get()->save();
else
history->Save();
}

View File

@@ -23,7 +23,6 @@ GhostController::GhostController(AbstractKart *kart,
StateManager::ActivePlayer *player)
: Controller(kart, player)
{
m_kart = kart;
} // GhostController
//-----------------------------------------------------------------------------

View File

@@ -53,10 +53,10 @@ public:
virtual void updateWeight() {};
// ------------------------------------------------------------------------
/** No physics for ghost kart. */
virtual void applyEngineForce (float force) {}
virtual void applyEngineForce (float force) {};
// ------------------------------------------------------------------------
// Not needed to create any physics for a ghost kart.
virtual void createPhysics() {}
virtual void createPhysics() {};
// ------------------------------------------------------------------------
const float getSuspensionLength(int index, int wheel) const
{ return m_all_physic_info[index].m_suspension_length[wheel]; }

View File

@@ -279,7 +279,7 @@ void World::reset()
race_manager->reset();
// Make sure to overwrite the data from the previous race.
if(!history->replayHistory()) history->initRecording();
if(ReplayRecorder::get()) ReplayRecorder::get()->init();
if(race_manager->willRecordRace()) ReplayRecorder::get()->init();
// Reset all data structures that depend on number of karts.
irr_driver->reset();
@@ -970,8 +970,7 @@ void World::update(float dt)
PROFILER_PUSH_CPU_MARKER("World::update (sub-updates)", 0x20, 0x7F, 0x00);
history->update(dt);
if(ReplayRecorder::get()) ReplayRecorder::get()->update(dt);
if(ReplayPlay::get()) ReplayPlay::get()->update(dt);
if(race_manager->willRecordRace()) ReplayRecorder::get()->update(dt);
if(history->replayHistory()) dt=history->getNextDelta();
WorldStatus::update(dt);
if (m_script_engine) m_script_engine->update(dt);

View File

@@ -76,6 +76,7 @@ RaceManager::RaceManager()
m_started_from_overworld = false;
m_have_kart_last_position_on_overworld = false;
setReverseTrack(false);
setRecordRace(false);
setTrack("jungle");
m_default_ai_list.clear();
setNumPlayers(0);

View File

@@ -350,6 +350,7 @@ private:
/** Determines if saved GP should be continued or not*/
bool m_continue_saved_gp;
bool m_will_record_race;
public:
RaceManager();
~RaceManager();
@@ -697,6 +698,16 @@ public:
{
return m_kart_last_position_on_overworld;
} // getKartLastPositionOnOverworld
// ------------------------------------------------------------------------
void setRecordRace(bool record)
{
m_will_record_race = record;
} // setRecordRace
// ------------------------------------------------------------------------
bool willRecordRace() const
{
return m_will_record_race;
} // willRecordRace
}; // RaceManager

View File

@@ -60,18 +60,6 @@ void ReplayPlay::reset()
}
} // reset
//-----------------------------------------------------------------------------
/** Updates all ghost karts.
* \param dt Time step size.
*/
void ReplayPlay::update(float dt)
{
// First update all ghost karts
for(unsigned int i=0; i<(unsigned int)m_ghost_karts.size(); i++)
m_ghost_karts[i].update(dt);
} // update
//-----------------------------------------------------------------------------
/** Loads the basic (ghost karts, reverse track) info in the replay file,
* required by race manager.

View File

@@ -48,7 +48,6 @@ private:
~ReplayPlay();
void readKartData(FILE *fd, char *next_line);
public:
void update(float dt);
void reset();
void load();
void loadBasicInfo();

View File

@@ -55,6 +55,8 @@ ReplayRecorder::~ReplayRecorder()
*/
void ReplayRecorder::init()
{
m_complete_replay = false;
m_incorrect_replay = false;
m_transform_events.clear();
m_physic_info.clear();
m_kart_replay_event.clear();
@@ -81,19 +83,14 @@ void ReplayRecorder::init()
#endif
} // init
//-----------------------------------------------------------------------------
/** Resets all ghost karts back to start position.
*/
void ReplayRecorder::reset()
{
} // reset
//-----------------------------------------------------------------------------
/** Saves the current replay data.
* \param dt Time step size.
*/
void ReplayRecorder::update(float dt)
{
if (m_incorrect_replay || m_complete_replay) return;
const World *world = World::getWorld();
unsigned int num_karts = world->getNumKarts();
@@ -104,6 +101,9 @@ void ReplayRecorder::update(float dt)
for(unsigned int i=0; i<num_karts; i++)
{
const AbstractKart *kart = world->getKart(i);
// Don't record give-up race
if (kart->isEliminated()) return;
if (kart->isGhostKart()) continue;
#ifdef DEBUG
m_count++;
@@ -126,6 +126,7 @@ void ReplayRecorder::update(float dt)
sprintf(buffer, "Can't store more events for kart %s.",
kart->getIdent().c_str());
Log::warn("ReplayRecorder", buffer);
m_incorrect_replay = true;
}
continue;
}
@@ -173,13 +174,25 @@ void ReplayRecorder::update(float dt)
r->m_on_nitro = nitro;
r->m_on_zipper = zipper;
} // for i
if (world->getPhase() == World::RESULT_DISPLAY_PHASE && !m_complete_replay)
{
m_complete_replay = true;
save();
}
} // update
//-----------------------------------------------------------------------------
/** Saves the replay data stored in the internal data structures.
*/
void ReplayRecorder::Save()
void ReplayRecorder::save()
{
if (m_incorrect_replay || !m_complete_replay)
{
Log::warn("ReplayRecorder", "Incomplete replay file will not be saved.");
return;
}
#ifdef DEBUG
printf("%d frames, %d removed because of frequency compression\n",
m_count, m_count_skipped_time);
@@ -194,6 +207,7 @@ void ReplayRecorder::Save()
Log::info("ReplayRecorder", "Replay saved in '%s'.\n", getReplayFilename().c_str());
fprintf(fd, "reverse: %d\n", (int)race_manager->getReverseTrack());
World *world = World::getWorld();
unsigned int num_karts = world->getNumKarts();
for (unsigned int real_karts = 0; real_karts < num_karts; real_karts++)
@@ -208,7 +222,6 @@ void ReplayRecorder::Save()
fprintf(fd, "difficulty: %d\n", race_manager->getDifficulty());
fprintf(fd, "track: %s\n", world->getTrack()->getIdent().c_str());
fprintf(fd, "laps: %d\n", race_manager->getNumLaps());
fprintf(fd, "reverse: %d\n", (int)race_manager->getReverseTrack());
unsigned int max_frames = (unsigned int)( stk_config->m_replay_max_time
/ stk_config->m_replay_dt );
@@ -245,5 +258,4 @@ void ReplayRecorder::Save()
} // for i
}
fclose(fd);
} // Save
} // save

View File

@@ -49,6 +49,10 @@ private:
/** Static pointer to the one instance of the replay object. */
static ReplayRecorder *m_replay_recorder;
bool m_complete_replay;
bool m_incorrect_replay;
#ifdef DEBUG
/** Counts overall number of events stored. */
unsigned int m_count;
@@ -66,8 +70,7 @@ private:
public:
void init();
void update(float dt);
void reset();
void Save();
void save();
// ------------------------------------------------------------------------
/** Creates a new instance of the replay object. */

View File

@@ -68,7 +68,9 @@ void TrackInfoScreen::loadedFromFile()
m_lap_spinner = getWidget<SpinnerWidget>("lap-spinner");
m_ai_kart_spinner = getWidget<SpinnerWidget>("ai-spinner");
m_reverse = getWidget<CheckBoxWidget>("reverse");
m_record_race = getWidget<CheckBoxWidget>("record");
m_reverse->setState(false);
m_record_race->setState(false);
m_highscore_label = getWidget<LabelWidget>("highscores");
@@ -209,6 +211,14 @@ void TrackInfoScreen::init()
else
m_reverse->setState(false);
// Record race or not
// -------------
const bool record_available = race_manager->getMinorMode() == RaceManager::MINOR_MODE_TIME_TRIAL;
m_record_race->setVisible(record_available);
getWidget<LabelWidget>("record-race-text")->setVisible(record_available);
if (record_available)
m_record_race->setState(false);
// ---- High Scores
m_highscore_label->setVisible(has_highscores);
@@ -358,6 +368,23 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name,
// checkbox.
updateHighScores();
}
else if (name == "record")
{
const bool record = m_record_race->getState();
race_manager->setRecordRace(record);
m_ai_kart_spinner->setValue(0);
// Disable AI when recording ghost race
if (record)
{
m_ai_kart_spinner->setActive(false);
race_manager->setNumKarts(race_manager->getNumLocalPlayers());
UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers();
}
else
{
m_ai_kart_spinner->setActive(true);
}
}
else if (name == "lap-spinner")
{
assert(race_manager->modeHasLaps());

View File

@@ -55,6 +55,9 @@ class TrackInfoScreen : public GUIEngine::Screen,
/** Check box for reverse mode. */
GUIEngine::CheckBoxWidget* m_reverse;
/** Check box for record race. */
GUIEngine::CheckBoxWidget* m_record_race;
/** The label of the highscore list. */
GUIEngine::LabelWidget* m_highscore_label;

View File

@@ -357,7 +357,7 @@ bool handleContextMenuAction(s32 cmdID)
}
else if (cmdID == DEBUG_SAVE_REPLAY)
{
ReplayRecorder::get()->Save();
ReplayRecorder::get()->save();
}
else if (cmdID == DEBUG_SAVE_HISTORY)
{