Compute and display a story mode timer (#4121)
This is the result of my previous work, with a port of the timer version that was developed for a 1.0 mod. It has been used by several players so no major issue should exist, though UI and other elements may require adjustment to smooth some rough edges. It features both a casual story mode timer storing the total time to complete the story mode (on by default) and a "speedrun" timer (off by default). The casual timer is paused whenever the player exits story mode, and supports play over multiple sessions. It is only displayed in the overworld and during challenges ; while the speedrun timer is permanently displayed. Fix #2907
This commit is contained in:
parent
48f4088894
commit
770d02b19b
@ -87,6 +87,23 @@
|
||||
</div>
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<checkbox id="story-mode-timer"/>
|
||||
<spacer width="1%" height="100%" />
|
||||
<label height="100%" I18N="In the ui settings" text="Enable the story mode timer" word_wrap="true"/>
|
||||
</div>
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
|
||||
<div layout="horizontal-row" width="100%" height="fit">
|
||||
<checkbox id="speedrun-timer"/>
|
||||
<spacer width="1%" height="100%" />
|
||||
<label id="speedrun-timer-text" height="100%" I18N="In the ui settings" text="Enable the speedrun timer" word_wrap="true"/>
|
||||
</div>
|
||||
|
||||
<spacer width="5" height="2%"/>
|
||||
</box>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Modify this file to change the last-modified date when you add/remove a file.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
|
||||
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
|
||||
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "challenges/challenge_status.hpp"
|
||||
#include "challenges/challenge_data.hpp"
|
||||
#include "challenges/story_mode_timer.hpp"
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
@ -30,20 +31,35 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
StoryModeStatus::StoryModeStatus(const XMLNode *node)
|
||||
{
|
||||
m_points = 0;
|
||||
m_points_before = 0;
|
||||
m_next_unlock_points = 0;
|
||||
m_first_time = true;
|
||||
m_easy_challenges = 0;
|
||||
m_medium_challenges = 0;
|
||||
m_hard_challenges = 0;
|
||||
m_best_challenges = 0;
|
||||
m_current_challenge = NULL;
|
||||
m_points = 0;
|
||||
m_points_before = 0;
|
||||
m_next_unlock_points = 0;
|
||||
m_first_time = true;
|
||||
m_easy_challenges = 0;
|
||||
m_medium_challenges = 0;
|
||||
m_hard_challenges = 0;
|
||||
m_best_challenges = 0;
|
||||
m_current_challenge = NULL;
|
||||
m_story_mode_finished = false;
|
||||
m_valid_speedrun_finished = false;
|
||||
m_story_mode_milliseconds = 0;
|
||||
m_speedrun_milliseconds = 0;
|
||||
|
||||
// If there is saved data, load it
|
||||
if(node)
|
||||
{
|
||||
node->get("first-time", &m_first_time);
|
||||
|
||||
// If the timer sub-nodes are missing, don't load junk data
|
||||
// Disable the timers if story mode has already been started.
|
||||
if(!node->get("finished", &m_story_mode_finished))
|
||||
m_story_mode_finished = !m_first_time;
|
||||
if(!node->get("speedrun-finished", &m_valid_speedrun_finished))
|
||||
m_valid_speedrun_finished = false;
|
||||
if(!node->get("story-ms", &m_story_mode_milliseconds))
|
||||
m_story_mode_milliseconds = -1;
|
||||
if(!node->get("speedrun-ms", &m_speedrun_milliseconds))
|
||||
m_speedrun_milliseconds = -1;
|
||||
} // if node
|
||||
} // StoryModeStatus
|
||||
|
||||
@ -317,9 +333,28 @@ void StoryModeStatus::grandPrixFinished()
|
||||
/** Writes the data of this StoryModeStatus to the specified stream.
|
||||
* \param out UTF stream to write to.
|
||||
*/
|
||||
void StoryModeStatus::save(UTFWriter &out)
|
||||
void StoryModeStatus::save(UTFWriter &out, bool current_player)
|
||||
{
|
||||
out << " <story-mode first-time=\"" << m_first_time << L"\">\n";
|
||||
if (story_mode_timer->playerLoaded() && current_player)
|
||||
{
|
||||
// Make sure the timer pauses time is correct
|
||||
if (story_mode_timer->isStoryModePaused())
|
||||
{
|
||||
story_mode_timer->unpauseTimer(/*loading*/ false);
|
||||
story_mode_timer->updateTimer();
|
||||
story_mode_timer->pauseTimer(/*loading*/ false);
|
||||
}
|
||||
|
||||
m_speedrun_milliseconds = story_mode_timer->getSpeedrunTime();
|
||||
m_story_mode_milliseconds = story_mode_timer->getStoryModeTime();
|
||||
}
|
||||
|
||||
out << " <story-mode first-time=\"" << m_first_time << "\"";
|
||||
out << " finished=\"" << m_story_mode_finished << "\"";
|
||||
out << " speedrun-finished=\"" << m_valid_speedrun_finished << "\"\n";
|
||||
out << " story-ms=\"" << m_story_mode_milliseconds << "\"";
|
||||
out << " speedrun-ms=\"" << m_speedrun_milliseconds << "\">\n";
|
||||
|
||||
std::map<std::string, ChallengeStatus*>::const_iterator i;
|
||||
for(i = m_challenges_state.begin();
|
||||
i != m_challenges_state.end(); i++)
|
||||
|
@ -73,6 +73,17 @@ private:
|
||||
int m_hard_challenges;
|
||||
int m_best_challenges;
|
||||
|
||||
/* Set to true after fort magma */
|
||||
bool m_story_mode_finished;
|
||||
|
||||
/* Set to true after fort magma if there was a valid speedrun active
|
||||
* This is used to know if m_speedrun_milliseconds contain valid data */
|
||||
bool m_valid_speedrun_finished;
|
||||
|
||||
// It overflows at over 500 hours
|
||||
int m_story_mode_milliseconds;
|
||||
int m_speedrun_milliseconds;
|
||||
|
||||
public:
|
||||
|
||||
StoryModeStatus(const XMLNode *node=NULL);
|
||||
@ -86,58 +97,83 @@ public:
|
||||
bool do_save=true);
|
||||
void raceFinished ();
|
||||
void grandPrixFinished ();
|
||||
void save (UTFWriter &out);
|
||||
void save (UTFWriter &out, bool current_player=false);
|
||||
void addStatus(ChallengeStatus *cs);
|
||||
void setCurrentChallenge(const std::string &challenge_id);
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the list of recently unlocked features (e.g. call at the end
|
||||
* of a race to know if any features were unlocked) */
|
||||
const std::vector<const ChallengeData*>
|
||||
getRecentlyCompletedChallenges() {return m_unlocked_features;}
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Clear the list of recently unlocked challenges */
|
||||
void clearUnlocked () {m_unlocked_features.clear(); }
|
||||
// ------------------------------------------------------------------------
|
||||
void clearUnlocked () {m_unlocked_features.clear(); }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the number of completed challenges. */
|
||||
int getNumCompletedChallenges () const { return (m_easy_challenges + m_medium_challenges +
|
||||
m_hard_challenges + m_best_challenges); }
|
||||
// ------------------------------------------------------------------------
|
||||
int getNumCompletedChallenges () const { return (m_easy_challenges + m_medium_challenges +
|
||||
m_hard_challenges + m_best_challenges); }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the number of challenges with the superTux time beaten in a lower difficulty. */
|
||||
int getNumReqMetInLowerDiff () const;
|
||||
// ------------------------------------------------------------------------
|
||||
int getNumReqMetInLowerDiff () const;
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the number of points accumulated. */
|
||||
int getPoints () const { return m_points; }
|
||||
// ------------------------------------------------------------------------
|
||||
int getPoints () const { return m_points; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the number of points before the previous point increase */
|
||||
int getPointsBefore () const { return m_points_before; }
|
||||
// ------------------------------------------------------------------------
|
||||
int getPointsBefore () const { return m_points_before; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the number of points needed by the next unlockable. 0 if none. */
|
||||
int getNextUnlockPoints () const { return m_next_unlock_points; }
|
||||
// ------------------------------------------------------------------------
|
||||
int getNextUnlockPoints () const { return m_next_unlock_points; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the number of fulfilled challenges at easy level. */
|
||||
int getNumEasyTrophies () const { return m_easy_challenges; }
|
||||
// ------------------------------------------------------------------------
|
||||
int getNumEasyTrophies () const { return m_easy_challenges; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/* Returns the number of fulfilled challenges at medium level. */
|
||||
int getNumMediumTrophies() const { return m_medium_challenges; }
|
||||
// ------------------------------------------------------------------------
|
||||
int getNumMediumTrophies() const { return m_medium_challenges; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the number of fulfilled challenges at hard level. */
|
||||
int getNumHardTrophies () const { return m_hard_challenges; }
|
||||
// ------------------------------------------------------------------------
|
||||
int getNumHardTrophies () const { return m_hard_challenges; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the number of fulfilled challenges at best level. */
|
||||
int getNumBestTrophies () const { return m_best_challenges; }
|
||||
// ------------------------------------------------------------------------
|
||||
int getNumBestTrophies () const { return m_best_challenges; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Sets if this is the first time the intro is shown. */
|
||||
void setFirstTime(bool ft) { m_first_time = ft; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setFirstTime(bool ft) { m_first_time = ft; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns if this is the first time the intro is shown. */
|
||||
bool isFirstTime() const { return m_first_time; }
|
||||
// ------------------------------------------------------------------------
|
||||
const ChallengeStatus *getCurrentChallengeStatus() const
|
||||
{
|
||||
return m_current_challenge;
|
||||
} // getCurrentChallengeStatus
|
||||
// ------------------------------------------------------------------------
|
||||
bool isFirstTime() const { return m_first_time; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Sets if the player has beaten Nolock */
|
||||
void setFinished() { m_story_mode_finished = true; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns if the player has beaten Nolock */
|
||||
bool isFinished() const { return m_story_mode_finished; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Sets if the player has finished a valid speedrun */
|
||||
void setSpeedrunFinished() { m_valid_speedrun_finished = true; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns if the player has finished a valid speedrun */
|
||||
bool isSpeedrunFinished() const { return m_valid_speedrun_finished; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Sets the story mode timer */
|
||||
void setStoryModeTimer(int milliseconds) { m_story_mode_milliseconds = milliseconds; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Gets the story mode timer
|
||||
* This is designed to be used on loading and once story mode is completed ;
|
||||
* it will return out-of-date values when the timer is running. */
|
||||
int getStoryModeTimer() { return m_story_mode_milliseconds; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Sets the story mode timer */
|
||||
void setSpeedrunTimer(int milliseconds) { m_speedrun_milliseconds = milliseconds; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Gets the speedrun timer
|
||||
* This is designed to be used on loading and once story mode is completed ;
|
||||
* it will return out-of-date values when the timer is running. */
|
||||
int getSpeedrunTimer() { return m_speedrun_milliseconds; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
const ChallengeStatus *getCurrentChallengeStatus() const { return m_current_challenge; }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns a challenge given the challenge id.
|
||||
*/
|
||||
const ChallengeStatus* getChallengeStatus(const std::string& id) const
|
||||
|
271
src/challenges/story_mode_timer.cpp
Normal file
271
src/challenges/story_mode_timer.cpp
Normal file
@ -0,0 +1,271 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2006-2019 SuperTuxKart-Team
|
||||
//
|
||||
// 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 "challenges/story_mode_timer.hpp"
|
||||
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "states_screens/dialogs/message_dialog.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
StoryModeTimer *story_mode_timer = 0;
|
||||
|
||||
StoryModeTimer::StoryModeTimer()
|
||||
{
|
||||
m_player_tested = false;
|
||||
reset();
|
||||
} // SpeedrunTimer
|
||||
|
||||
void StoryModeTimer::reset()
|
||||
{
|
||||
PlayerProfile *player = PlayerManager::getCurrentPlayer();
|
||||
|
||||
// May happen when there is no player profile at all
|
||||
if (player == NULL)
|
||||
{
|
||||
m_valid_speedrun_ended = false;
|
||||
m_story_mode_ended = false;
|
||||
m_stored_speedrun_milliseconds = 0;
|
||||
m_stored_story_mode_milliseconds = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_valid_speedrun_ended = player->isSpeedrunFinished();
|
||||
m_story_mode_ended = player->isFinished();
|
||||
m_stored_speedrun_milliseconds = player->getSpeedrunTimer();
|
||||
m_stored_story_mode_milliseconds = player->getStoryModeTimer();
|
||||
}
|
||||
|
||||
m_valid_speedrun_started = false;
|
||||
m_story_mode_started = false;
|
||||
m_speedrun_pause_active = false;
|
||||
m_story_mode_pause_active = false;
|
||||
m_loading_pause = false;
|
||||
m_player_can_speedrun = false;
|
||||
m_speedrun_milliseconds = 0;
|
||||
m_story_mode_milliseconds = 0;
|
||||
std::chrono::time_point<std::chrono::system_clock> now(std::chrono::system_clock::now());
|
||||
m_speedrun_total_pause_time = now-now;//the zero() function doesn't work
|
||||
m_story_mode_total_pause_time = now-now;
|
||||
}
|
||||
|
||||
void StoryModeTimer::startTimer()
|
||||
{
|
||||
// The speedrun timer runs even if not enabled, as long
|
||||
// as the conditions match, as the ovrehead is minimal
|
||||
// and it thus persist if the user disable/reenable it.
|
||||
if (!m_valid_speedrun_started && m_player_can_speedrun)
|
||||
{
|
||||
m_speedrun_start = std::chrono::system_clock::now();
|
||||
m_valid_speedrun_started = true;
|
||||
}
|
||||
|
||||
// The normal story mode timer runs along the speedrun timer
|
||||
// so that if speedrun mode is disabled, its value exists
|
||||
// and is correct
|
||||
if (!m_story_mode_started)
|
||||
{
|
||||
m_story_mode_start = std::chrono::system_clock::now();
|
||||
m_story_mode_started = true;
|
||||
}
|
||||
}
|
||||
|
||||
void StoryModeTimer::stopTimer()
|
||||
{
|
||||
if (m_valid_speedrun_started)
|
||||
{
|
||||
m_speedrun_end = std::chrono::system_clock::now();
|
||||
m_valid_speedrun_ended = true;
|
||||
}
|
||||
|
||||
if (m_story_mode_started)
|
||||
{
|
||||
m_story_mode_end = std::chrono::system_clock::now();
|
||||
m_story_mode_ended = true;
|
||||
}
|
||||
updateTimer();
|
||||
}
|
||||
|
||||
/* Pauses the story mode and speedrun timer, if applicable.
|
||||
* The speedrun timer is only paused on loading screens,
|
||||
* while the story mode timer can also be paused when
|
||||
* quitting the story mode. */
|
||||
void StoryModeTimer::pauseTimer(bool loading)
|
||||
{
|
||||
// Don't change the pause time if there is no run,
|
||||
// if it is finished, or if it is already set.
|
||||
|
||||
if ( m_valid_speedrun_started && !m_speedrun_pause_active &&
|
||||
!m_valid_speedrun_ended && loading)
|
||||
{
|
||||
pauseSpeedrunTimer();
|
||||
}
|
||||
if ( m_story_mode_started && !m_story_mode_pause_active &&
|
||||
!m_story_mode_ended)
|
||||
{
|
||||
pauseStoryModeTimer();
|
||||
m_loading_pause = loading;
|
||||
}
|
||||
} // pauseTimer
|
||||
|
||||
void StoryModeTimer::pauseSpeedrunTimer()
|
||||
{
|
||||
m_speedrun_pause_start = std::chrono::system_clock::now();
|
||||
m_speedrun_pause_active = true;
|
||||
}
|
||||
|
||||
void StoryModeTimer::pauseStoryModeTimer()
|
||||
{
|
||||
m_story_mode_pause_start = std::chrono::system_clock::now();
|
||||
m_story_mode_pause_active = true;
|
||||
}
|
||||
|
||||
|
||||
void StoryModeTimer::unpauseTimer(bool loading)
|
||||
{
|
||||
//Don't unpause if there is no run or no previous pause
|
||||
if (m_valid_speedrun_started && m_speedrun_pause_active && !m_valid_speedrun_ended && loading)
|
||||
{
|
||||
unpauseSpeedrunTimer();
|
||||
}
|
||||
if (m_story_mode_started && m_story_mode_pause_active &&
|
||||
!m_story_mode_ended && (m_loading_pause || ( !m_loading_pause && !loading)))
|
||||
{
|
||||
unpauseStoryModeTimer();
|
||||
}
|
||||
} //unpauseTimer
|
||||
|
||||
void StoryModeTimer::unpauseSpeedrunTimer()
|
||||
{
|
||||
std::chrono::time_point<std::chrono::system_clock> now(std::chrono::system_clock::now());
|
||||
m_speedrun_total_pause_time += now - m_speedrun_pause_start;
|
||||
m_speedrun_pause_active = false;
|
||||
|
||||
int milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(m_speedrun_total_pause_time).count();
|
||||
Log::verbose("StoryModeTimer", "Total speedrun pause time : %ims.",milliseconds);
|
||||
} // unpauseSpeedrunTimer
|
||||
|
||||
void StoryModeTimer::unpauseStoryModeTimer()
|
||||
{
|
||||
std::chrono::time_point<std::chrono::system_clock> now(std::chrono::system_clock::now());
|
||||
m_story_mode_total_pause_time += now - m_story_mode_pause_start;
|
||||
m_story_mode_pause_active = false;
|
||||
} // unpauseStoryModeTimer
|
||||
|
||||
void StoryModeTimer::updateTimer()
|
||||
{
|
||||
if (!m_player_tested)
|
||||
{
|
||||
reset();
|
||||
testPlayerRun();
|
||||
}
|
||||
|
||||
updateSpeedrunTimer();
|
||||
updateStoryModeTimer();
|
||||
} // updateTimer
|
||||
|
||||
void StoryModeTimer::updateSpeedrunTimer()
|
||||
{
|
||||
std::chrono::duration<double> elapsed_time;
|
||||
|
||||
if (m_valid_speedrun_ended)
|
||||
{
|
||||
elapsed_time = m_speedrun_end - m_speedrun_start - m_speedrun_total_pause_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::chrono::time_point<std::chrono::system_clock> now(std::chrono::system_clock::now());
|
||||
elapsed_time = now - m_speedrun_start - m_speedrun_total_pause_time;
|
||||
}
|
||||
|
||||
m_speedrun_milliseconds = m_stored_speedrun_milliseconds +
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(elapsed_time).count();
|
||||
}
|
||||
|
||||
void StoryModeTimer::updateStoryModeTimer()
|
||||
{
|
||||
std::chrono::duration<double> elapsed_time;
|
||||
|
||||
if (m_story_mode_ended)
|
||||
{
|
||||
elapsed_time = m_story_mode_end - m_story_mode_start - m_story_mode_total_pause_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::chrono::time_point<std::chrono::system_clock> now(std::chrono::system_clock::now());
|
||||
elapsed_time = now - m_story_mode_start - m_story_mode_total_pause_time;
|
||||
}
|
||||
m_story_mode_milliseconds = m_stored_story_mode_milliseconds +
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(elapsed_time).count();
|
||||
}
|
||||
|
||||
//Check if the current player has already entered story mode or not
|
||||
void StoryModeTimer::testPlayerRun()
|
||||
{
|
||||
PlayerProfile *player = PlayerManager::getCurrentPlayer();
|
||||
|
||||
// May happen when there is no player profile at all
|
||||
// Will be called again until a player profile is created
|
||||
if (player == NULL)
|
||||
return;
|
||||
|
||||
if (player->isFirstTime())
|
||||
{
|
||||
m_player_can_speedrun = true;
|
||||
}
|
||||
|
||||
|
||||
if(!m_player_can_speedrun && UserConfigParams::m_speedrun_mode)
|
||||
{
|
||||
UserConfigParams::m_speedrun_mode = false;
|
||||
new MessageDialog(_("Speedrun mode disabled. It can only be enabled if the game"
|
||||
" has not been closed since the launch of the story mode.\n\n"
|
||||
"Closing the game before the story mode's"
|
||||
" completion invalidates the timer.\n\n"
|
||||
"To use the speedrun mode, please use a new profile."),
|
||||
MessageDialog::MESSAGE_DIALOG_OK,
|
||||
NULL, false, false, 0.6f, 0.7f);
|
||||
}
|
||||
|
||||
m_player_tested = true;
|
||||
}
|
||||
|
||||
/* When the active player changes, resets and reload timer data */
|
||||
void StoryModeTimer::playerHasChanged()
|
||||
{
|
||||
m_player_tested = false;
|
||||
} // playerHasChanged
|
||||
|
||||
std::string StoryModeTimer::getTimerString()
|
||||
{
|
||||
if (UserConfigParams::m_speedrun_mode && !m_valid_speedrun_started && !m_valid_speedrun_ended)
|
||||
{
|
||||
return StringUtils::timeToString(/*time in seconds*/ 0,
|
||||
/*precision*/ 3, true, /* display hours*/ true);
|
||||
}
|
||||
|
||||
if (UserConfigParams::m_speedrun_mode)
|
||||
return StringUtils::timeToString(/*time in seconds*/ m_speedrun_milliseconds/1000.0f,
|
||||
/*precision*/ 3, true, /* display hours*/ true);
|
||||
else
|
||||
return StringUtils::timeToString(/*time in seconds*/ m_story_mode_milliseconds/1000.0f,
|
||||
/*precision*/ 0, true, /* display hours*/ true);
|
||||
} // getStoryModeTimerString
|
||||
|
||||
/* EOF */
|
90
src/challenges/story_mode_timer.hpp
Normal file
90
src/challenges/story_mode_timer.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2006-2019 SuperTuxKart-Team
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef HEADER_STORY_MODE_TIMER_HPP
|
||||
#define HEADER_STORY_MODE_TIMER_HPP
|
||||
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
|
||||
class StoryModeTimer
|
||||
{
|
||||
private:
|
||||
bool m_valid_speedrun_started, m_valid_speedrun_ended;
|
||||
bool m_story_mode_started, m_story_mode_ended;
|
||||
bool m_speedrun_pause_active, m_story_mode_pause_active;
|
||||
bool m_loading_pause;
|
||||
bool m_player_tested;
|
||||
bool m_player_can_speedrun;
|
||||
|
||||
//This stores the number of milliseconds to display with the counter
|
||||
int m_speedrun_milliseconds;
|
||||
int m_story_mode_milliseconds;
|
||||
|
||||
int m_stored_speedrun_milliseconds;
|
||||
int m_stored_story_mode_milliseconds;
|
||||
|
||||
std::chrono::time_point<std::chrono::system_clock> m_speedrun_start;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_speedrun_end;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_speedrun_pause_start;
|
||||
|
||||
std::chrono::time_point<std::chrono::system_clock> m_story_mode_start;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_story_mode_end;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_story_mode_pause_start;
|
||||
|
||||
std::chrono::duration<double> m_speedrun_total_pause_time;
|
||||
std::chrono::duration<double> m_story_mode_total_pause_time;
|
||||
|
||||
void reset();
|
||||
|
||||
void testPlayerRun();
|
||||
|
||||
void pauseSpeedrunTimer();
|
||||
void pauseStoryModeTimer();
|
||||
void unpauseSpeedrunTimer();
|
||||
void unpauseStoryModeTimer();
|
||||
void updateSpeedrunTimer();
|
||||
void updateStoryModeTimer();
|
||||
public:
|
||||
|
||||
StoryModeTimer();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Speedrun timer functions. */
|
||||
void startTimer();
|
||||
void stopTimer();
|
||||
void pauseTimer(bool loading);
|
||||
void unpauseTimer(bool loading);
|
||||
void updateTimer();
|
||||
|
||||
void playerHasChanged();
|
||||
std::string getTimerString();
|
||||
bool playerLoaded() const { return m_player_tested; }
|
||||
bool isStoryModePaused() const { return m_story_mode_pause_active; }
|
||||
bool playerCanRun() const { return m_player_can_speedrun; }
|
||||
bool isSpeedrunning() const { return m_valid_speedrun_started; }
|
||||
bool speedrunIsFinished() const { return m_valid_speedrun_ended; }
|
||||
int getStoryModeTime() const { return m_story_mode_milliseconds; }
|
||||
int getSpeedrunTime() const { return m_speedrun_milliseconds; }
|
||||
}; // StoryModeTimer
|
||||
|
||||
extern StoryModeTimer* story_mode_timer;
|
||||
|
||||
#endif
|
||||
|
||||
/* EOF */
|
@ -19,6 +19,7 @@
|
||||
#include "config/player_manager.hpp"
|
||||
|
||||
#include "achievements/achievements_manager.hpp"
|
||||
#include "challenges/story_mode_timer.hpp"
|
||||
#include "config/player_profile.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
@ -461,12 +462,18 @@ PlayerProfile *PlayerManager::getPlayer(const irr::core::stringw &name)
|
||||
*/
|
||||
void PlayerManager::setCurrentPlayer(PlayerProfile *player)
|
||||
{
|
||||
bool player_has_changed = false;
|
||||
if (m_current_player != player)
|
||||
{
|
||||
player_has_changed = true;
|
||||
save();
|
||||
race_manager->clearKartLastPositionOnOverworld();
|
||||
}
|
||||
|
||||
m_current_player = player;
|
||||
if(m_current_player)
|
||||
{
|
||||
m_current_player->computeActive();
|
||||
}
|
||||
|
||||
if (player_has_changed)
|
||||
story_mode_timer->playerHasChanged();
|
||||
} // setCurrentPlayer
|
||||
|
@ -217,8 +217,14 @@ void PlayerProfile::save(UTFWriter &out)
|
||||
out << " remember-password=\"" << m_remember_password << "\"\n";
|
||||
out << " default-kart-color=\"" << m_default_kart_color << "\">\n";
|
||||
{
|
||||
bool is_current_player = false;
|
||||
PlayerProfile *player = PlayerManager::getCurrentPlayer();
|
||||
|
||||
if (player != NULL && (getName() == player->getName()))
|
||||
is_current_player = true;
|
||||
|
||||
if(m_story_mode_status)
|
||||
m_story_mode_status->save(out);
|
||||
m_story_mode_status->save(out, is_current_player);
|
||||
|
||||
if(m_achievements_status)
|
||||
m_achievements_status->save(out);
|
||||
|
@ -145,7 +145,7 @@ public:
|
||||
virtual void requestSignOut() = 0;
|
||||
virtual bool isLoggedIn() const { return false; }
|
||||
const std::string getIconFilename() const;
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Sets the name of this player. */
|
||||
void setName(const core::stringw& name)
|
||||
{
|
||||
@ -155,7 +155,7 @@ public:
|
||||
m_local_name = name;
|
||||
} // setName
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the name of this player. */
|
||||
const core::stringw& getName() const
|
||||
{
|
||||
@ -163,7 +163,7 @@ public:
|
||||
return m_local_name;
|
||||
} // getName
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns true if this player is a guest account. */
|
||||
bool isGuestAccount() const
|
||||
{
|
||||
@ -172,80 +172,96 @@ public:
|
||||
#endif
|
||||
return m_is_guest_account;
|
||||
} // isGuestAccount
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the last used online name. */
|
||||
const core::stringw& getLastOnlineName() const
|
||||
{
|
||||
return m_last_online_name;
|
||||
} // getLastOnlineName
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Sets the last used online name. */
|
||||
void setLastOnlineName(const core::stringw &name)
|
||||
{
|
||||
m_last_online_name = name;
|
||||
} // setLastOnlineName
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the unique id of this player. */
|
||||
unsigned int getUniqueID() const { return m_unique_id; }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returnes if the feature (kart, track) is locked. */
|
||||
bool isLocked(const std::string &feature) const
|
||||
{
|
||||
return m_story_mode_status->isLocked(feature);
|
||||
} // isLocked
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns all active challenges. */
|
||||
void computeActive() { m_story_mode_status->computeActive(); }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the list of recently completed challenges. */
|
||||
std::vector<const ChallengeData*> getRecentlyCompletedChallenges()
|
||||
{
|
||||
return m_story_mode_status->getRecentlyCompletedChallenges();
|
||||
} // getRecently Completed Challenges
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Sets the currently active challenge. */
|
||||
void setCurrentChallenge(const std::string &name)
|
||||
{
|
||||
m_story_mode_status->setCurrentChallenge(name);
|
||||
} // setCurrentChallenge
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Callback when a GP is finished (to test if a challenge was
|
||||
* fulfilled). */
|
||||
void grandPrixFinished() { m_story_mode_status->grandPrixFinished(); }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
unsigned int getNumCompletedChallenges() const { return m_story_mode_status->getNumCompletedChallenges(); }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
unsigned int getPoints() const { return m_story_mode_status->getPoints(); }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
unsigned int getPointsBefore() const { return m_story_mode_status->getPointsBefore(); }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
unsigned int getNextUnlockPoints() const { return m_story_mode_status->getNextUnlockPoints(); }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
void setFirstTime(bool b) { m_story_mode_status->setFirstTime(b); }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
bool isFirstTime() const { return m_story_mode_status->isFirstTime(); }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
void setFinished() { m_story_mode_status->setFinished(); }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
bool isFinished() const { return m_story_mode_status->isFinished(); }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
void setSpeedrunFinished() { m_story_mode_status->setSpeedrunFinished(); }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
bool isSpeedrunFinished() { return m_story_mode_status->isSpeedrunFinished(); }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
void setStoryModeTimer(int ms) { m_story_mode_status->setStoryModeTimer(ms); }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
int getStoryModeTimer() { return m_story_mode_status->getStoryModeTimer(); }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
void setSpeedrunTimer(int ms) { m_story_mode_status->setSpeedrunTimer(ms); }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
int getSpeedrunTimer() { return m_story_mode_status->getSpeedrunTimer(); }
|
||||
// ----------------------------------------------------------------------------------------
|
||||
void clearUnlocked()
|
||||
{
|
||||
m_story_mode_status->clearUnlocked();
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns the current challenge for this player. */
|
||||
const ChallengeStatus* getCurrentChallengeStatus() const
|
||||
{
|
||||
return m_story_mode_status->getCurrentChallengeStatus();
|
||||
} // getCurrentChallengeStatus
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
const ChallengeStatus* getChallengeStatus(const std::string &id)
|
||||
{
|
||||
return m_story_mode_status->getChallengeStatus(id);
|
||||
} // getChallengeStatus
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
unsigned int getNumEasyTrophies() const
|
||||
{
|
||||
return m_story_mode_status->getNumEasyTrophies();
|
||||
} // getNumEasyTrophies
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
unsigned int getNumMediumTrophies() const
|
||||
{
|
||||
return m_story_mode_status->getNumMediumTrophies();
|
||||
@ -259,47 +275,47 @@ public:
|
||||
{
|
||||
return m_story_mode_status->getNumBestTrophies();
|
||||
} // getNumBestTrophies
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
AchievementsStatus* getAchievementsStatus()
|
||||
{
|
||||
return m_achievements_status;
|
||||
} // getAchievementsStatus
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns true if a session was saved for this player. */
|
||||
bool hasSavedSession() const { return m_saved_session; }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
StoryModeStatus* getStoryModeStatus() { return m_story_mode_status; }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** If a session was saved, return the id of the saved user. */
|
||||
int getSavedUserId() const
|
||||
{
|
||||
assert(m_saved_session);
|
||||
return m_saved_user_id;
|
||||
} // getSavedUserId
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** If a session was saved, return the token to use. */
|
||||
const std::string& getSavedToken() const
|
||||
{
|
||||
assert(m_saved_session);
|
||||
return m_saved_token;
|
||||
} // getSavedToken
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns if the last time this player was used it was used online or
|
||||
* offline. */
|
||||
bool wasOnlineLastTime() const { return m_last_was_online; }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Sets if this player was logged in last time it was used. */
|
||||
void setWasOnlineLastTime(bool b) { m_last_was_online = b; }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Returns if the last time this player was used it was used online or
|
||||
* offline. */
|
||||
bool rememberPassword() const { return m_remember_password; }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
/** Sets if this player was logged in last time it was used. */
|
||||
void setRememberPassword(bool b) { m_remember_password = b; }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
void setDefaultKartColor(float c) { m_default_kart_color = c; }
|
||||
// ------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
float getDefaultKartColor() const { return m_default_kart_color; }
|
||||
|
||||
}; // class PlayerProfile
|
||||
|
@ -603,6 +603,12 @@ namespace UserConfigParams
|
||||
PARAM_PREFIX BoolUserConfigParam m_display_fps
|
||||
PARAM_DEFAULT( BoolUserConfigParam(false, "show_fps",
|
||||
&m_video_group, "Display frame per seconds") );
|
||||
PARAM_PREFIX BoolUserConfigParam m_display_story_mode_timer
|
||||
PARAM_DEFAULT( BoolUserConfigParam(true, "show_story_mode_timer",
|
||||
&m_video_group, "Display the story mode timer") );
|
||||
PARAM_PREFIX BoolUserConfigParam m_speedrun_mode
|
||||
PARAM_DEFAULT( BoolUserConfigParam(false, "show_speedrun_timer",
|
||||
&m_video_group, "Display the speedrun timer") );
|
||||
PARAM_PREFIX IntUserConfigParam m_max_fps
|
||||
PARAM_DEFAULT( IntUserConfigParam(120, "max_fps",
|
||||
&m_video_group, "Maximum fps, should be at least 60") );
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#include "graphics/irr_driver.hpp"
|
||||
|
||||
#include "challenges/story_mode_timer.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "font/font_manager.hpp"
|
||||
#include "graphics/2dutils.hpp"
|
||||
@ -1850,6 +1852,48 @@ void IrrDriver::displayFPS()
|
||||
#endif
|
||||
} // updateFPS
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Displays the timer for Story Mode on the screen.
|
||||
* This can't be done in race or overworld GUIs as
|
||||
* the speedrun timer has to be displayed on all screens.
|
||||
*/
|
||||
void IrrDriver::displayStoryModeTimer()
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
gui::ScalableFont* font = GUIEngine::getHighresDigitFont();
|
||||
|
||||
core::stringw timer_string;
|
||||
timer_string = story_mode_timer->getTimerString().c_str();
|
||||
|
||||
//The normal timer size ; to not write over it
|
||||
core::dimension2du area = font->getDimension(L"99:99.99");
|
||||
int regular_timer_width = area.Width;
|
||||
int additional_height = 0;
|
||||
if (UserConfigParams::m_speedrun_mode)
|
||||
area = font->getDimension(L"99:99:99.999");
|
||||
else
|
||||
area = font->getDimension(L"99:99:99");
|
||||
|
||||
int screen_width = irr_driver->getActualScreenSize().Width;
|
||||
int screen_height = irr_driver->getActualScreenSize().Height;
|
||||
int speedrun_string_width = area.Width;
|
||||
int dist_from_right = speedrun_string_width + regular_timer_width + screen_width*4/100;
|
||||
|
||||
core::rect<s32> position(screen_width - dist_from_right, screen_height*2/100,
|
||||
screen_width , screen_height*6/100);
|
||||
|
||||
font->setColoredBorder(irr::video::SColor(255, 0, 32, 80));
|
||||
|
||||
if ( (UserConfigParams::m_speedrun_mode && story_mode_timer->speedrunIsFinished()) ||
|
||||
(!UserConfigParams::m_speedrun_mode && PlayerManager::getCurrentPlayer()->isFinished()) )
|
||||
font->draw(timer_string.c_str(), position, video::SColor(255, 0, 255, 0), false, false, NULL, true);
|
||||
else
|
||||
font->draw(timer_string.c_str(), position, video::SColor(255, 220, 255, 0), false, false, NULL, true);
|
||||
|
||||
font->disableColoredBorder();
|
||||
#endif
|
||||
} // displayStoryModeTimer
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Requess a screenshot from irrlicht, and save it in a file.
|
||||
*/
|
||||
|
@ -215,6 +215,7 @@ public:
|
||||
scene::IAnimatedMesh *getAnimatedMesh(const std::string &name);
|
||||
scene::IMesh *getMesh(const std::string &name);
|
||||
void displayFPS();
|
||||
void displayStoryModeTimer();
|
||||
bool OnEvent(const irr::SEvent &event);
|
||||
void setAmbientLight(const video::SColorf &light,
|
||||
bool force_SH_computation = true);
|
||||
|
@ -658,6 +658,7 @@ namespace GUIEngine
|
||||
|
||||
#include "guiengine/engine.hpp"
|
||||
|
||||
#include "challenges/story_mode_timer.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "font/bold_face.hpp"
|
||||
#include "font/digit_face.hpp"
|
||||
@ -1135,7 +1136,7 @@ namespace GUIEngine
|
||||
{
|
||||
g_device->getVideoDriver()
|
||||
->beginScene(true, true, video::SColor(255,100,101,140));
|
||||
renderLoading();
|
||||
renderLoading(true, true);
|
||||
g_device->getVideoDriver()->endScene();
|
||||
}
|
||||
} // init
|
||||
@ -1328,6 +1329,12 @@ namespace GUIEngine
|
||||
// draw FPS if enabled
|
||||
if ( UserConfigParams::m_display_fps ) irr_driver->displayFPS();
|
||||
|
||||
// draw speedrun timer if enabled
|
||||
if ( UserConfigParams::m_speedrun_mode ) irr_driver->displayStoryModeTimer();
|
||||
// Update the story mode and speedrun timer (even if not enabled)
|
||||
story_mode_timer->unpauseTimer(/* exit loading pause */ true);
|
||||
story_mode_timer->updateTimer();
|
||||
|
||||
g_driver->enableMaterial2D(false);
|
||||
|
||||
|
||||
@ -1349,7 +1356,7 @@ namespace GUIEngine
|
||||
// -----------------------------------------------------------------------
|
||||
std::vector<irr::video::ITexture*> g_loading_icons;
|
||||
|
||||
void renderLoading(bool clearIcons)
|
||||
void renderLoading(bool clearIcons, bool launching)
|
||||
{
|
||||
#ifndef SERVER_ONLY
|
||||
if (clearIcons) g_loading_icons.clear();
|
||||
@ -1421,6 +1428,17 @@ namespace GUIEngine
|
||||
g_device->setEventReceiver(NULL);
|
||||
g_device->run();
|
||||
g_device->setEventReceiver(EventHandler::get());
|
||||
|
||||
// If launch is finished, pause & display the story mode timers
|
||||
if ( !launching)
|
||||
{
|
||||
// For speedruns only, display the timer on loading screens
|
||||
if (UserConfigParams::m_speedrun_mode)
|
||||
irr_driver->displayStoryModeTimer();
|
||||
|
||||
//pause the timer during loading
|
||||
story_mode_timer->pauseTimer(true);
|
||||
}
|
||||
#endif
|
||||
} // renderLoading
|
||||
|
||||
@ -1434,7 +1452,7 @@ namespace GUIEngine
|
||||
|
||||
g_device->getVideoDriver()
|
||||
->beginScene(true, true, video::SColor(255,100,101,140));
|
||||
renderLoading(false);
|
||||
renderLoading(false, true);
|
||||
g_device->getVideoDriver()->endScene();
|
||||
}
|
||||
else
|
||||
|
@ -232,7 +232,7 @@ namespace GUIEngine
|
||||
void render(float dt, bool is_loading = false);
|
||||
|
||||
/** \brief renders a "loading" screen */
|
||||
void renderLoading(bool clearIcons = true);
|
||||
void renderLoading(bool clearIcons = true, bool launching = false);
|
||||
|
||||
/** \brief to spice up a bit the loading icon : add icons to the loading screen */
|
||||
void addLoadingIcon(irr::video::ITexture* icon);
|
||||
|
@ -176,6 +176,7 @@
|
||||
#include "addons/news_manager.hpp"
|
||||
#include "audio/music_manager.hpp"
|
||||
#include "audio/sfx_manager.hpp"
|
||||
#include "challenges/story_mode_timer.hpp"
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "config/hardware_stats.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
@ -1791,7 +1792,7 @@ void initRest()
|
||||
|
||||
GUIEngine::init(device, driver, StateManager::get());
|
||||
|
||||
GUIEngine::renderLoading();
|
||||
GUIEngine::renderLoading(true, true);
|
||||
input_manager = new InputManager();
|
||||
// Get into menu mode initially.
|
||||
input_manager->setMode(InputManager::MENU);
|
||||
@ -2360,6 +2361,11 @@ int main(int argc, char *argv[])
|
||||
race_manager->setupPlayerKartInfo();
|
||||
race_manager->startNew(false);
|
||||
}
|
||||
|
||||
// Create the story mode timer before going in the main loop
|
||||
// as it needs to be able to run continuously
|
||||
story_mode_timer = new StoryModeTimer();
|
||||
|
||||
main_loop->run();
|
||||
|
||||
} // try
|
||||
@ -2469,6 +2475,7 @@ static void cleanSuperTuxKart()
|
||||
GUIEngine::cleanUp();
|
||||
GUIEngine::clearScreenCache();
|
||||
if(font_manager) delete font_manager;
|
||||
if(story_mode_timer) delete story_mode_timer;
|
||||
|
||||
// Now finish shutting down objects which a separate thread. The
|
||||
// RequestManager has been signaled to shut down as early as possible,
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "audio/music_manager.hpp"
|
||||
#include "audio/sfx_manager.hpp"
|
||||
#include "challenges/story_mode_timer.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "guiengine/emoji_keyboard.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
@ -56,9 +57,12 @@ RacePausedDialog::RacePausedDialog(const float percentWidth,
|
||||
ModalDialog(percentWidth, percentHeight)
|
||||
{
|
||||
m_self_destroy = false;
|
||||
m_from_overworld = false;
|
||||
|
||||
if (dynamic_cast<OverWorld*>(World::getWorld()) != NULL)
|
||||
{
|
||||
loadFromFile("overworld_dialog.stkgui");
|
||||
m_from_overworld = true;
|
||||
}
|
||||
else if (!NetworkConfig::get()->isNetworking())
|
||||
{
|
||||
@ -222,6 +226,11 @@ GUIEngine::EventPropagation
|
||||
else
|
||||
{
|
||||
StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
|
||||
|
||||
// Pause story mode timer when quitting story mode
|
||||
if (m_from_overworld)
|
||||
story_mode_timer->pauseTimer(/*loading screen*/ false);
|
||||
|
||||
if (race_manager->raceWasStartedFromOverworld())
|
||||
{
|
||||
OverWorld::enterOverWorld();
|
||||
|
@ -37,6 +37,7 @@ class RacePausedDialog : public GUIEngine::ModalDialog,
|
||||
{
|
||||
private:
|
||||
bool m_self_destroy;
|
||||
bool m_from_overworld;
|
||||
|
||||
GUIEngine::TextBoxWidget* m_text_box;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "states_screens/main_menu_screen.hpp"
|
||||
|
||||
#include "addons/news_manager.hpp"
|
||||
#include "challenges/story_mode_timer.hpp"
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
@ -475,6 +476,10 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
{
|
||||
NetworkConfig::get()->unsetNetworking();
|
||||
PlayerProfile *player = PlayerManager::getCurrentPlayer();
|
||||
|
||||
// Start the story mode (and speedrun) timer
|
||||
story_mode_timer->startTimer();
|
||||
|
||||
if (player->isFirstTime())
|
||||
{
|
||||
CutsceneWorld::setUseDuration(true);
|
||||
@ -493,6 +498,9 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unpause the story mode timer when entering back the story mode
|
||||
story_mode_timer->unpauseTimer(/* exit loading pause */ false);
|
||||
|
||||
const std::string default_kart = UserConfigParams::m_default_kart;
|
||||
if (player->isLocked(default_kart))
|
||||
{
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "addons/news_manager.hpp"
|
||||
#include "audio/sfx_manager.hpp"
|
||||
#include "audio/sfx_base.hpp"
|
||||
#include "challenges/story_mode_timer.hpp"
|
||||
#include "config/hardware_stats.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
@ -38,6 +39,7 @@
|
||||
#include "guiengine/widget.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "online/request_manager.hpp"
|
||||
#include "states_screens/dialogs/message_dialog.hpp"
|
||||
#include "states_screens/main_menu_screen.hpp"
|
||||
#include "states_screens/options/options_screen_audio.hpp"
|
||||
#include "states_screens/options/options_screen_general.hpp"
|
||||
@ -242,6 +244,30 @@ void OptionsScreenUI::init()
|
||||
assert( fps != NULL );
|
||||
fps->setState( UserConfigParams::m_display_fps );
|
||||
|
||||
CheckBoxWidget* story_timer = getWidget<CheckBoxWidget>("story-mode-timer");
|
||||
assert( story_timer != NULL );
|
||||
story_timer->setState( UserConfigParams::m_display_story_mode_timer );
|
||||
CheckBoxWidget* speedrun_timer = getWidget<CheckBoxWidget>("speedrun-timer");
|
||||
assert( speedrun_timer != NULL );
|
||||
if (UserConfigParams::m_speedrun_mode)
|
||||
{
|
||||
if (!story_mode_timer->playerCanRun())
|
||||
{
|
||||
UserConfigParams::m_speedrun_mode = false;
|
||||
new MessageDialog(_("Speedrun mode disabled. It can only be enabled if the game"
|
||||
" has not been closed since the launch of the story mode.\n\n"
|
||||
"Closing the game before the story mode's"
|
||||
" completion invalidates the timer.\n\n"
|
||||
"To use the speedrun mode, please use a new profile."),
|
||||
MessageDialog::MESSAGE_DIALOG_OK,
|
||||
NULL, false, false, 0.6f, 0.7f);
|
||||
}
|
||||
}
|
||||
speedrun_timer->setState( UserConfigParams::m_speedrun_mode );
|
||||
speedrun_timer->setVisible( UserConfigParams::m_display_story_mode_timer );
|
||||
getWidget<LabelWidget>("speedrun-timer-text")
|
||||
->setVisible(UserConfigParams::m_display_story_mode_timer);
|
||||
|
||||
// --- select the right skin in the spinner
|
||||
bool currSkinFound = false;
|
||||
const std::string& user_skin = UserConfigParams::m_skin_file;
|
||||
@ -403,6 +429,46 @@ void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, con
|
||||
assert( fps != NULL );
|
||||
UserConfigParams::m_display_fps = fps->getState();
|
||||
}
|
||||
else if (name == "story-mode-timer")
|
||||
{
|
||||
CheckBoxWidget* story_timer = getWidget<CheckBoxWidget>("story-mode-timer");
|
||||
assert( story_timer != NULL );
|
||||
UserConfigParams::m_display_story_mode_timer = story_timer->getState();
|
||||
|
||||
CheckBoxWidget* speedrun_timer = getWidget<CheckBoxWidget>("speedrun-timer");
|
||||
assert( speedrun_timer != NULL );
|
||||
speedrun_timer->setActive( UserConfigParams::m_display_story_mode_timer );
|
||||
getWidget<LabelWidget>("speedrun-timer-text")
|
||||
->setActive(UserConfigParams::m_display_story_mode_timer);
|
||||
|
||||
// Disable speedrun mode if the story mode timer is disabled
|
||||
if (!UserConfigParams::m_display_story_mode_timer)
|
||||
{
|
||||
UserConfigParams::m_speedrun_mode = false;
|
||||
speedrun_timer->setState(false);
|
||||
}
|
||||
|
||||
}
|
||||
else if (name == "speedrun-timer")
|
||||
{
|
||||
CheckBoxWidget* speedrun_timer = getWidget<CheckBoxWidget>("speedrun-timer");
|
||||
assert( speedrun_timer != NULL );
|
||||
if (speedrun_timer->getState())
|
||||
{
|
||||
if (!story_mode_timer->playerCanRun())
|
||||
{
|
||||
speedrun_timer->setState(false);
|
||||
new MessageDialog(_("Speedrun mode can only be enabled if the game has not"
|
||||
" been closed since the launch of the story mode.\n\n"
|
||||
"Closing the game before the story mode's"
|
||||
" completion invalidates the timer.\n\n"
|
||||
"To use the speedrun mode, please use a new profile."),
|
||||
MessageDialog::MESSAGE_DIALOG_OK,
|
||||
NULL, false, false, 0.6f, 0.7f);
|
||||
}
|
||||
}
|
||||
UserConfigParams::m_speedrun_mode = speedrun_timer->getState();
|
||||
}
|
||||
#endif
|
||||
} // eventCallback
|
||||
|
||||
|
@ -24,6 +24,7 @@ using namespace irr;
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include "challenges/story_mode_timer.hpp"
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
@ -289,6 +290,14 @@ void RaceGUI::renderGlobal(float dt)
|
||||
|
||||
if (!m_enabled) return;
|
||||
|
||||
// Display the story mode timer if not in speedrun mode
|
||||
// If in speedrun mode, it is taken care of in GUI engine
|
||||
// as it must be displayed in all the game's screens
|
||||
if (UserConfigParams::m_display_story_mode_timer &&
|
||||
!UserConfigParams::m_speedrun_mode &&
|
||||
race_manager->raceWasStartedFromOverworld())
|
||||
irr_driver->displayStoryModeTimer();
|
||||
|
||||
// MiniMap is drawn when the players wait for the start countdown to end
|
||||
drawGlobalMiniMap();
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "states_screens/race_gui_overworld.hpp"
|
||||
|
||||
#include "challenges/challenge_status.hpp"
|
||||
#include "challenges/story_mode_timer.hpp"
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
@ -196,6 +197,12 @@ void RaceGUIOverworld::renderGlobal(float dt)
|
||||
drawTrophyPoints();
|
||||
}
|
||||
|
||||
// Display the story mode timer if not in speedrun mode
|
||||
// If in speedrun mode, it is taken care of in GUI engine
|
||||
// as it must be displayed in all the game's screens
|
||||
if (UserConfigParams::m_display_story_mode_timer && !UserConfigParams::m_speedrun_mode)
|
||||
irr_driver->displayStoryModeTimer();
|
||||
|
||||
drawGlobalMiniMap();
|
||||
#endif
|
||||
} // renderGlobal
|
||||
@ -261,6 +268,9 @@ void RaceGUIOverworld::drawTrophyPoints()
|
||||
size*2, pos.UpperLeftCorner.Y + size);
|
||||
core::rect<s32> source(core::position2di(0, 0), m_trophy[3]->getSize());
|
||||
|
||||
float place_between_trophies =
|
||||
PlayerManager::getCurrentPlayer()->isLocked("difficulty_best") ? size*2.0f : size*1.0f;
|
||||
|
||||
// Draw trophies icon and the number of trophy obtained by type
|
||||
for (unsigned int i=0;i<4;i++)
|
||||
{
|
||||