]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/game.cpp
Fix new compiler warnings thrown by gcc-4.6
[quix0rs-blobwars.git] / src / game.cpp
1 /*
2 Copyright (C) 2004-2010 Parallel Realities
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the 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 */
20
21 #include "game.h"
22
23 void newGame()
24 {
25         game.clear();
26         gameData.clear();
27         map.persistantList.clear();
28         engine.practice = false;
29
30         game.skill = engine.skill;
31 }
32
33 void showInGameOptions()
34 {
35         if (!engine.loadWidgets(_("data/inGameWidgets")))
36         {
37                 graphics.showErrorAndExit(ERR_FILE, _("data/inGameWidgets"));
38         }
39
40         graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
41
42         int cont, options, escape, quit, escapeyes, escapeno, warnno, warnyes, quitno, quityes, train, trainno, trainyes, restart, restartno, restartyes;
43         cont = options = escape = quit = escapeyes = escapeno = warnno = warnyes = quitno = quityes = train = trainno = trainyes = restart = restartno = restartyes = 0;
44
45         engine.setWidgetVariable("continue", &cont);
46         engine.setWidgetVariable("options", &options);
47         engine.setWidgetVariable("escape", &escape);
48         engine.setWidgetVariable("restart", &restart);
49         engine.setWidgetVariable("quit", &quit);
50         engine.setWidgetVariable("train", &train);
51
52         engine.setWidgetVariable("warnno", &warnno);
53         engine.setWidgetVariable("warnyes", &warnyes);
54         
55         engine.setWidgetVariable("restartno", &restartno);
56         engine.setWidgetVariable("restartyes", &restartyes);
57
58         engine.setWidgetVariable("quitno", &quitno);
59         engine.setWidgetVariable("quityes", &quityes);
60         
61         engine.setWidgetVariable("trainno", &quitno);
62         engine.setWidgetVariable("trainyes", &quityes);
63         
64         engine.setWidgetVariable("escapeno", &escapeno);
65         engine.setWidgetVariable("escapeyes", &escapeyes);
66
67         engine.showWidgetGroup("warning", false);
68         engine.showWidgetGroup("restartconf", false);
69         engine.showWidgetGroup("escapeconf", false);
70         engine.showWidgetGroup("quitconf", false);
71         engine.showWidgetGroup("trainconf", false);
72         
73         if ((map.isBossMission) || (engine.practice) || (strcmp(map.name, "Space Station") == 0))
74         {
75                 engine.enableWidget("escape", false);
76                 engine.enableWidget("restart", false);
77         }
78                 
79         if (!engine.practice)
80         {
81                 engine.showWidget("train", false);
82         }
83         else
84         {
85                 engine.showWidget("quit", false);
86         }
87
88         engine.flushInput();
89         engine.clearInput();
90
91         drawWidgets();
92         audio.playMenuSound(2);
93         
94         int menuSound = -1;
95
96         while (true)
97         {
98                 graphics.updateScreen();                
99                 engine.getInput();
100                 config.populate();
101
102                 if ((config.isControl(CONTROL::PAUSE)) || (engine.keyState[SDLK_ESCAPE]))
103                 {
104                         engine.keyState[SDLK_ESCAPE] = 0;
105                         config.resetControl(CONTROL::PAUSE);
106                         break;
107                 }
108                 
109                 menuSound = engine.processWidgets();
110
111                 if (menuSound)
112                 {
113                         graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
114                         drawWidgets();
115                         audio.playMenuSound(menuSound);
116                 }
117
118                 if (cont)
119                 {
120                         break;
121                 }
122
123                 if (escape)
124                 {
125                         engine.showWidgetGroup("options", false);
126
127                         if (!gameData.stagePreviouslyCleared(game.stageName))
128                         {
129                                 engine.showWidgetGroup("warning", true);
130                                 engine.highlightWidget("warnno");
131                         }
132                         else
133                         {
134                                 engine.showWidgetGroup("escapeconf", true);
135                                 engine.highlightWidget("escapeno");
136                         }
137
138                         graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
139                         drawWidgets();
140                         escape = 0;
141                 }
142
143                 if ((escapeyes) || (warnyes))
144                 {
145                         audio.stopMusic();
146                         audio.stopAmbiance();
147                         addTeleportParticles(player.x, player.y, 50, SND_TELEPORT3);
148                         dropCarriedItems();
149                         game.setMissionOver(MIS_PLAYERESCAPE);
150                         break;
151                 }
152
153                 if (options)
154                 {
155                         showOptions();
156                         break;
157                 }
158
159                 if ((warnno) || (quitno) || (escapeno) || (trainno) || (restartno))
160                 {
161                         engine.highlightWidget("continue");
162                         engine.showWidgetGroup("options", true);
163                         engine.showWidgetGroup("warning", false);
164                         engine.showWidgetGroup("trainconf", false);
165                         engine.showWidgetGroup("escapeconf", false);
166                         engine.showWidgetGroup("quitconf", false);
167                         engine.showWidgetGroup("restartconf", false);
168                         
169                         if (!engine.practice)
170                         {
171                                 engine.showWidget("train", false);
172                         }
173                         else
174                         {
175                                 engine.showWidget("quit", false);
176                         }
177                         
178                         graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
179                         drawWidgets();
180                         quitno = trainno = warnno = escapeno = restartno = 0;
181                 }
182
183                 if (quit)
184                 {
185                         engine.showWidgetGroup("options", false);
186                         engine.showWidgetGroup("quitconf", true);
187                         engine.highlightWidget("quitno");
188
189                         graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
190                         drawWidgets();
191                         quit = 0;
192                 }
193                 
194                 if (train)
195                 {
196                         engine.showWidgetGroup("options", false);
197                         engine.showWidgetGroup("trainconf", true);
198                         engine.highlightWidget("trainno");
199
200                         graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
201                         drawWidgets();
202                         train = 0;
203                 }
204                 
205                 if (restart)
206                 {
207                         engine.showWidgetGroup("options", false);
208                         engine.showWidgetGroup("restartconf", true);
209                         engine.highlightWidget("restartno");
210
211                         graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
212                         drawWidgets();
213                         restart = 0;
214                 }
215
216                 if ((quityes) || (trainyes))
217                 {
218                         game.setMissionOver(MIS_PLAYERQUIT);
219                         break;
220                 }
221                 
222                 if (restartyes)
223                 {
224                         game.setMissionOver(MIS_PLAYERRESTART);
225                         SDL_FillRect(graphics.screen, NULL, graphics.black);
226                         audio.stopMusic();
227                         audio.stopAmbiance();
228                         graphics.delay(500);
229                         break;
230                 }
231
232                 SDL_Delay(16);
233         }
234 }
235
236 void doGameStuff()
237 {
238         engine.getInput();
239         config.populate();
240         replayData.read(config.command);
241         
242         if (game.missionOverReason == MIS_INPROGRESS)
243         {
244                 config.doPause();
245         }
246
247         engine.doFrameLoop();
248
249         graphics.updateScreen();
250         graphics.animateSprites();
251         graphics.drawBackground();
252
253         doEffects();
254         doTrains();
255         doTraps();
256         drawMap();
257         doLineDefs();
258         doSwitches();
259         doItems();
260         doBullets();
261         doMIAs();
262         
263         if (map.isBossMission)
264         {
265                 doBosses();
266         }
267         
268         doEnemies();
269         doObstacles();
270         doTeleporters();
271         
272         if (map.isBlizzardLevel)
273         {
274                 doWind();
275         }
276         
277         doParticles();
278         
279         if ((SDL_GetAppState() & SDL_APPINPUTFOCUS) == 0)
280         {
281                 engine.paused = true;
282         }
283         
284         replayData.set(config.command); 
285         replayData.commit();
286 }
287
288 int gameover()
289 {
290         audio.stopMusic();
291         audio.stopAmbiance();
292         
293         if (!engine.loadWidgets(_("data/gameOverWidgets")))
294         {
295                 graphics.showErrorAndExit(ERR_FILE, _("data/gameOverWidgets"));
296         }
297
298         SDL_Surface *gameover = graphics.quickSprite("Game Over", graphics.loadImage("gfx/main/gameover.png"));
299         graphics.setTransparent(gameover);
300
301         audio.loadGameOverMusic();
302         audio.playMusic();
303
304         engine.flushInput();
305         engine.clearInput();
306
307         unsigned int frameLimit = SDL_GetTicks() + 16;
308
309         bool showGameOverOptions = false;
310         int cont, quit, menuSound;
311         cont = quit = menuSound = 0;
312
313         engine.setWidgetVariable("gameOverNo", &cont);
314         engine.setWidgetVariable("gameOverYes", &quit);
315         
316         if (game.canContinue > 1)
317         {
318                 Widget *widget = engine.getWidgetByName("gameOverNo");
319                 char postfix[100];
320                 snprintf(postfix, sizeof postfix, " (%d)", game.canContinue);
321                 strlcat(widget->label, postfix, sizeof widget->label);
322         }
323
324         while (true)
325         {
326                 if (menuSound)
327                         audio.playMenuSound(menuSound);
328
329                 doGameStuff();
330                 drawMapTopLayer();
331
332                 graphics.blit(gameover, 320, 240, graphics.screen, true);
333
334                 if (engine.userAccepts())
335                 {
336                         if (!showGameOverOptions)
337                         {
338                                 showGameOverOptions = true;
339                                 engine.showWidgetGroup("gameover", true);
340                                 engine.highlightWidget("gameOverNo");
341                                 engine.flushInput();
342                                 engine.clearInput();
343                         }
344
345                         // Can't continue on a boss mission or if no checkpoints reached!
346                         if ((map.isBossMission) || (!game.canContinue))
347                         {
348                                 engine.showWidgetGroup("gameover", false);
349                                 quit = 1;
350                         }
351                 }
352                 
353                 if (showGameOverOptions)
354                 {
355                         drawWidgets();
356                         menuSound = engine.processWidgets();
357                 }
358
359                 if ((cont) || (quit))
360                         break;
361
362                 engine.delay(frameLimit);
363                 frameLimit = SDL_GetTicks() + 16;
364         }
365
366         if (quit)
367         {
368                 audio.fadeMusic();
369                 graphics.fadeToBlack();
370                 map.clear();
371                 
372                 return SECTION_TITLE;
373         }
374
375         game.continueFromCheckPoint = true;
376         audio.stopMusic();
377         audio.reloadLevelMusic();
378
379         return SECTION_GAME;
380 }
381
382 void showMissionInformation()
383 {
384         SDL_FillRect(graphics.screen, NULL, graphics.black);
385         graphics.updateScreen();
386
387         SDL_Surface *panel = graphics.createSurface(400, 300);
388         SDL_Surface *panelBack = graphics.alphaRect(400, 300, 0x00, 0x00, 0x00);
389         SDL_SetColorKey(panel, (SDL_SRCCOLORKEY|SDL_RLEACCEL), SDL_MapRGB(panel->format, 0, 0, 0));
390
391         graphics.drawRect(1, 1, 398, 298, graphics.black, graphics.white, panelBack);
392
393         char message[256];
394         int col1 = 25;
395         int col2 = 375;
396         int y = 30;
397
398         Objective *objective;
399
400         graphics.setFontSize(0);
401
402         graphics.setFontSize(3);
403         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
404         graphics.drawString(_(game.stageName), 200, 20, TXT_CENTERED, panel);
405
406         graphics.setFontSize(0);
407
408         y += 20;
409
410         if (map.totalMIAs > 0)
411         {
412                 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
413                 snprintf(message, sizeof message, _("Rescue %d MIAs"), map.requiredMIAs);
414                 graphics.drawString(message, col1, y, TXT_LEFT, panel);
415
416                 if (map.foundMIAs < map.requiredMIAs)
417                 {
418                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
419                         snprintf(message, sizeof message, "%d / %d", map.foundMIAs, map.requiredMIAs);
420                         graphics.drawString(message, col2, y, TXT_RIGHT, panel);
421                 }
422                 else
423                 {
424                         graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
425                         graphics.drawString(_("Completed"), col2, y, TXT_RIGHT, panel);
426                 }
427         }
428
429         objective = (Objective*)map.objectiveList.getHead();
430
431         while (objective->next != NULL)
432         {
433                 objective = (Objective*)objective->next;
434
435                 y += 20;
436
437                 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
438                 
439                 if ((game.skill < 3) &&  (strstr(objective->description, "L.R.T.S.")) && (!gameData.completedWorld))
440                 {
441                         graphics.drawString(_("???? ???????? ????"), col1, y, TXT_LEFT, panel);
442                 }
443                 else
444                 {
445                         graphics.drawString(_(objective->description), col1, y, TXT_LEFT, panel);
446                 }
447                 
448                 // this is a fake objective (for the 4th Ancient Tomb)
449                 if (objective->targetValue == -1)
450                 {
451                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
452                         graphics.drawString(_("Incomplete"), col2, y, TXT_RIGHT, panel);
453                 }
454                 else if (objective->currentValue < objective->targetValue)
455                 {
456                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
457                         if (objective->targetValue == 1)
458                         {
459                                 graphics.drawString(_("Incomplete"), col2, y, TXT_RIGHT, panel);
460                         }
461                         else
462                         {
463                                 snprintf(message, sizeof message, "%d / %d", objective->currentValue, objective->targetValue);
464                                 graphics.drawString(message, col2, y, TXT_RIGHT, panel);
465                         }
466                 }
467                 else
468                 {
469                         graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
470                         graphics.drawString(_("Completed"), col2, y, TXT_RIGHT, panel);
471                 }
472         }
473         
474         if (game.skill == 3)
475         {
476                 graphics.setFontColor(0xff, 0xff, 0x00, 0x00, 0x00, 0x00);
477                 snprintf(message, sizeof message, _("Time Limit - %d:%.2d Minutes"), map.remainingMinutes, map.remainingSeconds);
478                 graphics.drawString(message, 200, 260, TXT_CENTERED, panel);
479         }
480         
481         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
482         graphics.drawString(_("Press Fire to Continue"), 200, 280, TXT_CENTERED, panel);
483
484         engine.flushInput();
485         engine.clearInput();
486
487         int px, py;
488
489         map.getRandomEntityPosition(&px, &py);
490         map.getRandomEntityPosition(&player.tx, &player.ty);
491
492         player.x = px;
493         player.y = py;
494
495         unsigned int frameLimit = SDL_GetTicks() + 16;
496                 
497         while (true)
498         {
499                 if ((int)player.x < player.tx) player.x += 2;
500                 if ((int)player.x > player.tx) player.x -= 2;
501                 if ((int)player.y < player.ty) player.y += 2;
502                 if ((int)player.y > player.ty) player.y -= 2;
503
504                 if (Collision::collision(player.x, player.y, 5, 5, player.tx, player.ty, 5, 5))
505                         map.getRandomEntityPosition(&player.tx, &player.ty);
506
507                 engine.setPlayerPosition((int)player.x, (int)player.y, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
508
509                 doGameStuff();
510                 drawMapTopLayer();
511                 graphics.blit(panelBack, 320, 220, graphics.screen, true);
512                 graphics.blit(panel, 320, 220, graphics.screen, true);
513
514                 engine.delay(frameLimit);
515                 frameLimit = SDL_GetTicks() + 16;
516
517                 if (engine.userAccepts())
518                         break;
519         }
520
521         SDL_FreeSurface(panel);
522         SDL_FreeSurface(panelBack);
523
524         SDL_FillRect(graphics.screen, NULL, graphics.black);
525         graphics.delay(1000);
526 }
527
528 void beamInPlayer()
529 {
530         game.getCheckPoint(&player.x, &player.y);
531         
532         int beamInTime = 180;
533         
534         unsigned int frameLimit = SDL_GetTicks() + 16;
535         
536         audio.playSound(SND_TELEPORT1, CH_ANY);
537         
538         engine.setPlayerPosition((int)player.x, (int)player.y, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
539         
540         while (beamInTime > 0)
541         {
542                 engine.delay(frameLimit);
543                 frameLimit = SDL_GetTicks() + 16;
544                 
545                 doGameStuff();
546                 drawMapTopLayer();
547                 
548                 if ((beamInTime % 10) == 0)
549                         addTeleportParticles(player.x + 10, player.y + 10, 50, -1);
550                 
551                 beamInTime--;
552         }
553         
554         game.getCheckPoint(&player.x, &player.y);
555         
556         player.dx = 0;
557         player.dy = 0;
558         player.immune = 120;
559         player.environment = ENV_AIR;
560         player.oxygen = 7;
561         player.fuel = 7;
562         Math::removeBit(&player.flags, ENT_FLIES);
563 }
564
565 int doGame()
566 {
567         graphics.setFontSize(0);
568
569         SDL_FillRect(graphics.screen, NULL, graphics.black);
570         graphics.delay(1000);
571
572         Uint32 then, frames, frameLimit, millis;
573         Uint32 start, cur;
574
575         #if DEBUG
576         Uint32 now, frameCounter;
577         char fps[10];
578         strlcpy(fps, "fps", sizeof fps);
579         #endif
580
581         engine.messageTime = -1;
582         engine.messagePriority = -1;
583
584         audio.playMusic();
585         audio.playAmbiance();
586
587         if (!game.continueFromCheckPoint)
588         {
589                 player.health = -99;
590
591                 if ((!map.isBossMission) && (replayData.replayMode == REPLAY_MODE::NONE))
592                 {
593                         showMissionInformation();
594                 }
595
596                 game.levelsStarted++;
597         }
598         else
599         {
600                 game.useObjectiveCheckPoint();
601         }
602
603         player.setVelocity(0, 1);
604         player.baseThink = 60;
605         player.health = MAX_HEALTH;
606
607         if (game.continueFromCheckPoint)
608         {
609                 player.health = (MAX_HEALTH / 2);
610                 player.setSprites(graphics.getSprite("BobRight", true), graphics.getSprite("BobLeft", true), graphics.getSprite("BobSpin", true));
611         }
612         else
613         {
614                 player.currentWeapon = &weapon[WP_PISTOL];
615         }
616
617         game.resetMissionOver();
618
619         frameLimit = SDL_GetTicks() + 16;
620         frames = millis = 0;
621         start = then = SDL_GetTicks();
622 #ifdef DEBUG
623         frameCounter = SDL_GetTicks();
624 #endif
625
626         if ((strcmp(map.name, "Space Station") == 0) && (!game.continueFromCheckPoint))
627         {
628                 beamInPlayer();
629         }
630         else
631         {
632                 resetPlayer();
633         }
634
635         engine.flushInput();
636         engine.clearInput();
637
638         debug(("Map Clipping is %d %d %d %d\n", map.limitLeft, map.limitRight, map.limitUp, map.limitDown));
639
640         game.continueFromCheckPoint = false;
641
642         engine.paused = false;
643
644         while (true)
645         {
646                 ++frames;
647                 ++millis;
648                 cur = SDL_GetTicks();
649
650                 if (game.missionOverReason != MIS_PLAYEROUT)
651                 {
652                         engine.setPlayerPosition((int)player.x, (int)player.y, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
653                 }
654
655                 doSpawnPoints();
656                 doGameStuff();
657
658                 doPlayer();
659                 raiseWaterLevel();
660
661                 if ((player.environment == ENV_SLIME) || (player.environment == ENV_LAVA) || (player.health < 1))
662                 {
663                         if (player.health < 1)
664                         {
665                                 game.setMissionOver(MIS_PLAYERDEAD);
666                                 audio.fadeMusic();
667                                 audio.stopAmbiance();
668                         }
669                         else
670                         {
671                                 game.setMissionOver(MIS_PLAYEROUT);
672                                 player.immune = 130;
673                         }
674                 }
675
676                 if (config.isControl(CONTROL::MAP))
677                 {
678                         if (!map.isBossMission)
679                         {
680                                 showMap((int)(player.x / 32), (int)(player.y / 32));
681                         }
682                         else
683                         {
684                                 engine.setInfoMessage("Automap is not available!", 1, INFO_HINT);
685                         }
686                 }
687
688                 drawMapTopLayer();
689                 doStatusBar();
690                 doMusicInfo(cur - start);
691
692                 if ((engine.keyState[SDLK_ESCAPE]) && (game.missionOver == 0))
693                 {
694                         if (replayData.replayMode == REPLAY_MODE::NONE)
695                         {
696                                 showInGameOptions();
697                         }
698                         else
699                         {
700                                 exit(0);
701                         }
702                 }
703
704                 if (allObjectivesCompleted())
705                 {
706                         if (game.missionOver == 0)
707                         {
708                                 if (map.isBossMission)
709                                 {
710                                         map.killAllEnemies();
711                                 }
712                                 
713                                 audio.stopMusic();
714                                 audio.stopAmbiance();
715
716                                 game.setMissionOver(MIS_COMPLETE);
717                                 engine.setInfoMessage("All Required Objectives Met - Mission Complete", 10, INFO_OBJECTIVE);
718                         }
719                 }
720
721                 if (game.missionOver > 0)
722                 {
723                         game.missionOver--;
724                 
725                         if (game.missionOver == 0)
726                         {
727                                 if (game.missionOverReason == MIS_PLAYEROUT)
728                                 {
729                                         SDL_FillRect(graphics.screen, NULL, graphics.black);
730                                         graphics.updateScreen();
731                                         graphics.delay(1000);
732                                         engine.flushInput();
733                                         engine.clearInput();
734                                         resetPlayer();
735                                         game.resetMissionOver();
736                                 }
737                                 else
738                                 {
739                                         if (game.missionOverReason == MIS_COMPLETE)
740                                         {
741                                                 game.missionOver = MAX_FPS * 2;
742                                                 
743                                                 if (strcmp(map.name, "Space Station") != 0)
744                                                 {
745                                                         addTeleportParticles(player.x, player.y, 50, SND_TELEPORT3);
746                                                         dropCarriedItems();
747                                                         game.missionOverReason = MIS_PLAYERESCAPE;
748                                                 }
749                                                 else
750                                                 {
751                                                         break;
752                                                 }
753                                         }
754                                         else if (game.missionOverReason == MIS_GAMECOMPLETE)
755                                         {
756                                                 addTeleportParticles(player.x, player.y, 50, SND_TELEPORT3);
757                                                 game.missionOverReason = MIS_PLAYERESCAPE;
758                                                 game.missionOver = MAX_FPS * 4;
759                                         }
760                                         else
761                                         {
762                                                 if (replayData.replayMode != REPLAY_MODE::NONE)
763                                                 {
764                                                         exit(0);
765                                                 }
766                                         
767                                                 break;
768                                         }
769                                 }
770                         }
771                 }
772
773                 Math::limitInt(&(--game.lastComboTime), 0, 60);
774
775                 if (millis >= 60)
776                 {
777                         millis = 0;
778                         
779                         if ((game.missionOverReason == MIS_INPROGRESS) || (game.missionOverReason == MIS_PLAYEROUT))
780                         {
781                                 game.incrementMissionTime();
782                                 
783                                 if (game.skill == 3)
784                                 {
785                                         doTimeRemaining();
786                                 }
787                         }
788                 }
789
790                 if (engine.paused)
791                 {
792                         doPauseInfo();
793                         audio.pause();
794                 }
795
796                 while (engine.paused)
797                 {
798                         engine.getInput();
799                         config.populate();
800                         config.doPause();
801                         graphics.updateScreen();
802                         then = SDL_GetTicks();
803                         frames = 0;
804
805                         if (!engine.paused)
806                         {
807                                 audio.resume();
808                         }
809
810                         SDL_Delay(16);
811                 }
812                 
813                 if ((engine.keyState[SDLK_F3]) && (engine.cheatSkipLevel))
814                 {
815                         autoCompleteAllObjectives(true);
816                         engine.keyState[SDLK_F3] = 0;
817                         engine.setInfoMessage("Skipping Mission...", 2, INFO_OBJECTIVE);
818                 }
819                 
820                 #if DEBUG
821                 if (engine.keyState[SDLK_F1])
822                 {
823                         autoCompleteAllObjectives(false);
824                 }               
825                 #endif
826                 
827                 if (replayData.replayMode != REPLAY_MODE::PLAYBACK)
828                 {
829                         engine.delay(frameLimit);
830                 }
831                 else if (!replayData.fast)
832                 {
833                         engine.delay(frameLimit);
834                 }
835                 
836                 if (engine.keyState[SDLK_F5])
837                 {
838                         replayData.fast = !replayData.fast;
839                         engine.keyState[SDLK_F5] = 0;
840                 }
841                 
842                 frameLimit = SDL_GetTicks()  + 16;
843                 
844                 if (game.missionOverReason == MIS_GAMECOMPLETE)
845                         frameLimit = SDL_GetTicks() + 64;
846
847                 #if DEBUG
848                 static Graphics::SurfaceCache fpsCache;
849                 graphics.drawString(fps, 600, 30, true, graphics.screen, fpsCache);
850
851                 if (SDL_GetTicks() > frameCounter + 500)
852                 {
853                         now = SDL_GetTicks();
854                         snprintf(fps, sizeof fps, "%2.2f fps", ((double)frames*1000)/(now - then));
855                         then = frameCounter = SDL_GetTicks();
856                         frames = 0;
857                 }
858                 #endif
859         }
860
861         if (allObjectivesCompleted())
862         {
863                 if (strcmp(map.name, "Final Battle") == 0)
864                 {
865                         game.missionOverReason = MIS_GAMECOMPLETE;
866                 }
867                 else
868                 {
869                         game.missionOverReason = MIS_COMPLETE;
870                 }
871         }
872
873         switch (game.missionOverReason)
874         {
875                 case MIS_COMPLETE:
876                         if (strcmp(map.name, "Space Station"))
877                         {
878                                 graphics.delay(1000);
879                                 audio.loadMusic("music/grasslands");
880                                 audio.playMusic();
881                                 graphics.fadeToBlack();
882                                 
883                                 bool previouslyCompleted = gameData.stagePreviouslyCleared(game.stageName);
884                                 
885                                 showMissionClear();
886                                 
887                                 if (engine.practice)
888                                 {
889                                         return SECTION_TITLE;
890                                 }
891                                 
892                                 if (!previouslyCompleted)
893                                 {
894                                         checkEndCutscene();
895                                 }
896                                 return SECTION_HUB;
897                         }
898                         else
899                         {
900                                 graphics.fadeToBlack();
901                                 processPostMissionData();
902                                 saveGame();
903                                 game.setMapName("data/finalBattle");
904                                 game.setStageName("Final Battle");
905                                 return SECTION_GAME;
906                         }
907                         break;
908                         
909                 case MIS_GAMECOMPLETE:
910                         SDL_FillRect(graphics.screen, NULL, graphics.white);
911                         graphics.updateScreen();
912                         graphics.fadeToBlack();
913                         
914                         // we've finished the game. Extreme mode is now available! :)
915                         engine.extremeAvailable = true;
916                         map.clear();
917                         graphics.free();
918                         audio.free();
919                         checkEndCutscene();
920                         return SECTION_CREDITS;
921                         break;
922
923                 case MIS_TIMEUP:
924                         game.canContinue = 0;
925                 case MIS_PLAYERDEAD:
926                         if (player.health > -60)
927                         {
928                                 player.health = -99;
929                                 gibPlayer();
930                         }
931                         return SECTION_GAMEOVER;
932                         break;
933
934                 case MIS_PLAYERESCAPE:
935                         game.escapes++;
936                         if (gameData.stagePreviouslyCleared(game.stageName))
937                         {
938                                 processPostMissionData();
939                                 saveGame();
940                         }
941                         return SECTION_HUB;
942                         break;
943                         
944                 case MIS_PLAYERRESTART:
945                         clearAllMissionData();
946                         return SECTION_GAME;
947                         break;
948
949                 default:
950                         return SECTION_TITLE;
951                         break;
952         }
953
954         return SECTION_TITLE;
955 }