1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2006-2019 SuperTuxKart-Team
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #include "challenges/story_mode_timer.hpp"
20 
21 #include "config/player_manager.hpp"
22 #include "config/user_config.hpp"
23 #include "states_screens/dialogs/message_dialog.hpp"
24 #include "utils/string_utils.hpp"
25 #include "utils/time.hpp"
26 #include "utils/translation.hpp"
27 
28 StoryModeTimer *story_mode_timer = 0;
29 
StoryModeTimer()30 StoryModeTimer::StoryModeTimer()
31 {
32     m_player_tested           = false;
33     m_valid_speedrun_ended    = false;
34     m_story_mode_ended        = false;
35     m_stored_speedrun_milliseconds   = 0;
36     m_stored_story_mode_milliseconds = 0;
37     m_valid_speedrun_started  = false;
38     m_story_mode_started      = false;
39     m_speedrun_pause_active   = false;
40     m_story_mode_pause_active = false;
41     m_loading_pause           = false;
42     m_player_can_speedrun     = false;
43     m_speedrun_milliseconds   = 0;
44     m_story_mode_milliseconds = 0;
45     m_speedrun_total_pause_time = 0;
46     m_story_mode_total_pause_time = 0;
47     m_speedrun_start = 0;
48     m_speedrun_end = 0;
49     m_speedrun_pause_start = 0;
50 
51     m_story_mode_start = 0;
52     m_story_mode_end = 0;
53     m_story_mode_pause_start = 0;
54 
55     m_speedrun_total_pause_time = 0;
56     m_story_mode_total_pause_time = 0;
57 
58 }  // SpeedrunTimer
59 
reset()60 void StoryModeTimer::reset()
61 {
62     PlayerProfile *player = PlayerManager::getCurrentPlayer();
63 
64     // May happen when there is no player profile at all
65     if (player == NULL)
66     {
67         m_valid_speedrun_ended    = false;
68         m_story_mode_ended        = false;
69         m_stored_speedrun_milliseconds   = 0;
70         m_stored_story_mode_milliseconds = 0;
71     }
72     else
73     {
74         m_valid_speedrun_ended    = player->isSpeedrunFinished();
75         m_story_mode_ended        = player->isFinished();
76         m_stored_speedrun_milliseconds   = player->getSpeedrunTimer();
77         m_stored_story_mode_milliseconds = player->getStoryModeTimer();
78     }
79 
80     m_valid_speedrun_started  = false;
81     m_story_mode_started      = false;
82     m_speedrun_pause_active   = false;
83     m_story_mode_pause_active = false;
84     m_loading_pause           = false;
85     m_player_can_speedrun     = false;
86     m_speedrun_milliseconds   = 0;
87     m_story_mode_milliseconds = 0;
88     m_speedrun_total_pause_time = 0;
89     m_story_mode_total_pause_time = 0;
90     m_speedrun_start = 0;
91     m_speedrun_end = 0;
92     m_speedrun_pause_start = 0;
93 
94     m_story_mode_start = 0;
95     m_story_mode_end = 0;
96     m_story_mode_pause_start = 0;
97 
98     m_speedrun_total_pause_time = 0;
99     m_story_mode_total_pause_time = 0;
100 }
101 
startTimer()102 void StoryModeTimer::startTimer()
103 {
104     // The speedrun timer runs even if not enabled, as long
105     // as the conditions match, as the ovrehead is minimal
106     // and it thus persist if the user disable/reenable it.
107     if (!m_valid_speedrun_started && m_player_can_speedrun)
108     {
109         m_speedrun_start = StkTime::getMonoTimeMs();
110         m_valid_speedrun_started = true;
111     }
112 
113     // The normal story mode timer runs along the speedrun timer
114     // so that if speedrun mode is disabled, its value exists
115     // and is correct
116     if (!m_story_mode_started)
117     {
118         m_story_mode_start = StkTime::getMonoTimeMs();
119         m_story_mode_end = m_story_mode_start;
120         m_story_mode_started = true;
121     }
122 }
123 
stopTimer()124 void StoryModeTimer::stopTimer()
125 {
126     if (m_valid_speedrun_started)
127     {
128         m_speedrun_end = StkTime::getMonoTimeMs();
129         m_valid_speedrun_ended = true;
130     }
131 
132     if (m_story_mode_started)
133     {
134         m_story_mode_end = StkTime::getMonoTimeMs();
135         m_story_mode_ended = true;
136     }
137     updateTimer();
138 }
139 
140 /* Pauses the story mode and speedrun timer, if applicable.
141  * The speedrun timer is only paused on loading screens,
142  * while the story mode timer can also be paused when
143  * quitting the story mode. */
pauseTimer(bool loading)144 void StoryModeTimer::pauseTimer(bool loading)
145 {
146     // Don't change the pause time if there is no run,
147     // if it is finished, or if it is already set.
148 
149     if ( m_valid_speedrun_started && !m_speedrun_pause_active &&
150          !m_valid_speedrun_ended && loading)
151     {
152         pauseSpeedrunTimer();
153     }
154     if ( m_story_mode_started && !m_story_mode_pause_active &&
155          !m_story_mode_ended)
156     {
157         pauseStoryModeTimer();
158         m_loading_pause = loading;
159     }
160 } // pauseTimer
161 
pauseSpeedrunTimer()162 void StoryModeTimer::pauseSpeedrunTimer()
163 {
164     m_speedrun_pause_start = StkTime::getMonoTimeMs();
165     m_speedrun_pause_active = true;
166 }
167 
pauseStoryModeTimer()168 void StoryModeTimer::pauseStoryModeTimer()
169 {
170     m_story_mode_pause_start = StkTime::getMonoTimeMs();
171     m_story_mode_pause_active = true;
172 }
173 
174 
unpauseTimer(bool loading)175 void StoryModeTimer::unpauseTimer(bool loading)
176 {
177     //Don't unpause if there is no run or no previous pause
178     if (m_valid_speedrun_started && m_speedrun_pause_active && !m_valid_speedrun_ended && loading)
179     {
180         unpauseSpeedrunTimer();
181     }
182     if (m_story_mode_started && m_story_mode_pause_active &&
183         !m_story_mode_ended && (m_loading_pause || ( !m_loading_pause && !loading)))
184     {
185         unpauseStoryModeTimer();
186     }
187 } //unpauseTimer
188 
unpauseSpeedrunTimer()189 void StoryModeTimer::unpauseSpeedrunTimer()
190 {
191     uint64_t now = StkTime::getMonoTimeMs();
192     m_speedrun_total_pause_time += now - m_speedrun_pause_start;
193     m_speedrun_pause_active = false;
194 
195     Log::verbose("StoryModeTimer", "Total speedrun pause time : %ims.", (int)m_speedrun_total_pause_time);
196 } // unpauseSpeedrunTimer
197 
unpauseStoryModeTimer()198 void StoryModeTimer::unpauseStoryModeTimer()
199 {
200     uint64_t now = StkTime::getMonoTimeMs();
201     m_story_mode_total_pause_time += now - m_story_mode_pause_start;
202     m_story_mode_pause_active = false;
203 } // unpauseStoryModeTimer
204 
updateTimer()205 void StoryModeTimer::updateTimer()
206 {
207     if (!m_player_tested)
208     {
209         reset();
210         testPlayerRun();
211     }
212 
213     updateSpeedrunTimer();
214     updateStoryModeTimer();
215 } // updateTimer
216 
updateSpeedrunTimer()217 void StoryModeTimer::updateSpeedrunTimer()
218 {
219     if (m_stored_speedrun_milliseconds < 0)
220     {
221         m_speedrun_milliseconds = -1;
222         return;
223     }
224 
225     uint64_t elapsed_time;
226 
227     if (m_valid_speedrun_ended)
228     {
229         elapsed_time = m_speedrun_end - m_speedrun_start - m_speedrun_total_pause_time;
230     }
231     else
232     {
233         uint64_t now = StkTime::getMonoTimeMs();
234         elapsed_time = now - m_speedrun_start - m_speedrun_total_pause_time;
235     }
236 
237     m_speedrun_milliseconds = m_stored_speedrun_milliseconds + elapsed_time;
238 }
239 
updateStoryModeTimer()240 void StoryModeTimer::updateStoryModeTimer()
241 {
242     if (m_stored_story_mode_milliseconds < 0)
243     {
244         m_story_mode_milliseconds = -1;
245         return;
246     }
247 
248     uint64_t elapsed_time;
249 
250     if (m_story_mode_ended)
251     {
252         elapsed_time = m_story_mode_end - m_story_mode_start - m_story_mode_total_pause_time;
253     }
254     else
255     {
256         uint64_t now = StkTime::getMonoTimeMs();
257         elapsed_time = now - m_story_mode_start - m_story_mode_total_pause_time;
258     }
259     m_story_mode_milliseconds = m_stored_story_mode_milliseconds + elapsed_time;
260 }
261 
262 //Check if the current player has already entered story mode or not
testPlayerRun()263 void StoryModeTimer::testPlayerRun()
264 {
265     PlayerProfile *player = PlayerManager::getCurrentPlayer();
266 
267     // May happen when there is no player profile at all
268     // Will be called again until a player profile is created
269     if (player == NULL)
270         return;
271 
272     if (player->isFirstTime())
273     {
274         m_player_can_speedrun = true;
275     }
276 
277 
278     if(!m_player_can_speedrun && UserConfigParams::m_speedrun_mode)
279     {
280         UserConfigParams::m_speedrun_mode = false;
281         new MessageDialog(_("Speedrun mode disabled. It can only be enabled if the game"
282                             " has not been closed since the launch of the story mode.\n\n"
283                             "Closing the game before the story mode's"
284                             " completion invalidates the timer.\n\n"
285                             "To use the speedrun mode, please use a new profile."),
286                             MessageDialog::MESSAGE_DIALOG_OK,
287                             NULL, false, false, 0.6f, 0.7f);
288     }
289 
290     m_player_tested = true;
291 }
292 
293 /* When the active player changes, resets and reload timer data */
playerHasChanged()294 void StoryModeTimer::playerHasChanged()
295 {
296     m_player_tested = false;
297 } // playerHasChanged
298 
getTimerString()299 std::string StoryModeTimer::getTimerString()
300 {
301     if (UserConfigParams::m_speedrun_mode && !m_valid_speedrun_started && !m_valid_speedrun_ended)
302     {
303         return StringUtils::timeToString(/*time in seconds*/ 0,
304                                          /*precision*/ 3, true, /* display hours*/ true);
305     }
306 
307     if (UserConfigParams::m_speedrun_mode)
308         return StringUtils::timeToString(/*time in seconds*/ m_speedrun_milliseconds/1000.0f,
309                                          /*precision*/ 3, true, /* display hours*/ true);
310     else
311         return StringUtils::timeToString(/*time in seconds*/ m_story_mode_milliseconds/1000.0f,
312                                          /*precision*/ 0, true, /* display hours*/ true);
313 } // getStoryModeTimerString
314 
315 /* EOF */
316