]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/game.cpp
Coalesce printf() statements in main.cpp, make them translatable.
[quix0rs-blobwars.git] / src / game.cpp
1 /*
2 Copyright (C) 2004-2011 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[SDL_SCANCODE_ESCAPE]))
103                 {
104                         engine.keyState[SDL_SCANCODE_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         replayData.set(config.command); 
280         replayData.commit();
281 }
282
283 int gameover()
284 {
285         audio.stopMusic();
286         audio.stopAmbiance();
287         
288         if (!engine.loadWidgets(_("data/gameOverWidgets")))
289         {
290                 graphics.showErrorAndExit(ERR_FILE, _("data/gameOverWidgets"));
291         }
292
293         SDL_Surface *gameover = graphics.quickSprite("Game Over", graphics.loadImage("gfx/main/gameover.png"));
294         graphics.setTransparent(gameover);
295
296         audio.loadGameOverMusic();
297         audio.playMusic();
298
299         engine.flushInput();
300         engine.clearInput();
301
302         unsigned int frameLimit = SDL_GetTicks() + 16;
303
304         bool showGameOverOptions = false;
305         int cont, quit, menuSound;
306         cont = quit = menuSound = 0;
307
308         engine.setWidgetVariable("gameOverNo", &cont);
309         engine.setWidgetVariable("gameOverYes", &quit);
310         
311         if (game.canContinue > 1)
312         {
313                 Widget *widget = engine.getWidgetByName("gameOverNo");
314                 char postfix[100];
315                 snprintf(postfix, sizeof postfix, " (%d)", game.canContinue);
316                 strlcat(widget->label, postfix, sizeof widget->label);
317         }
318
319         while (true)
320         {
321                 if (menuSound)
322                         audio.playMenuSound(menuSound);
323
324                 doGameStuff();
325                 drawMapTopLayer();
326
327                 graphics.blit(gameover, 320, 240, graphics.screen, true);
328
329                 if (engine.userAccepts())
330                 {
331                         if (!showGameOverOptions)
332                         {
333                                 showGameOverOptions = true;
334                                 engine.showWidgetGroup("gameover", true);
335                                 engine.highlightWidget("gameOverNo");
336                                 engine.flushInput();
337                                 engine.clearInput();
338                         }
339
340                         // Can't continue on a boss mission or if no checkpoints reached!
341                         if ((map.isBossMission) || (!game.canContinue))
342                         {
343                                 engine.showWidgetGroup("gameover", false);
344                                 quit = 1;
345                         }
346                 }
347                 
348                 if (showGameOverOptions)
349                 {
350                         drawWidgets();
351                         menuSound = engine.processWidgets();
352                 }
353
354                 if ((cont) || (quit))
355                         break;
356
357                 engine.delay(frameLimit);
358                 frameLimit = SDL_GetTicks() + 16;
359         }
360
361         if (quit)
362         {
363                 audio.fadeMusic();
364                 graphics.fadeToBlack();
365                 map.clear();
366                 
367                 return SECTION_TITLE;
368         }
369
370         game.continueFromCheckPoint = true;
371         audio.stopMusic();
372         audio.reloadLevelMusic();
373
374         return SECTION_GAME;
375 }
376
377 void showMissionInformation()
378 {
379         SDL_FillRect(graphics.screen, NULL, graphics.black);
380         graphics.updateScreen();
381
382         SDL_Surface *panel = graphics.createSurface(400, 300);
383         SDL_Surface *panelBack = graphics.alphaRect(400, 300, 0x00, 0x00, 0x00);
384         SDL_SetColorKey(panel, SDL_TRUE, SDL_MapRGB(panel->format, 0, 0, 0));
385
386         graphics.drawRect(1, 1, 398, 298, graphics.black, graphics.white, panelBack);
387
388         char message[256];
389         int col1 = 25;
390         int col2 = 375;
391         int y = 30;
392
393         Objective *objective;
394
395         graphics.setFontSize(0);
396
397         graphics.setFontSize(3);
398         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
399         graphics.drawString(_(game.stageName), 200, 20, TXT_CENTERED, panel);
400
401         graphics.setFontSize(0);
402
403         y += 20;
404
405         if (map.totalMIAs > 0)
406         {
407                 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
408                 snprintf(message, sizeof message, _("Rescue %d MIAs"), map.requiredMIAs);
409                 graphics.drawString(message, col1, y, TXT_LEFT, panel);
410
411                 if (map.foundMIAs < map.requiredMIAs)
412                 {
413                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
414                         snprintf(message, sizeof message, "%d / %d", map.foundMIAs, map.requiredMIAs);
415                         graphics.drawString(message, col2, y, TXT_RIGHT, panel);
416                 }
417                 else
418                 {
419                         graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
420                         graphics.drawString(_("Completed"), col2, y, TXT_RIGHT, panel);
421                 }
422         }
423
424         objective = (Objective*)map.objectiveList.getHead();
425
426         while (objective->next != NULL)
427         {
428                 objective = (Objective*)objective->next;
429
430                 y += 20;
431
432                 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
433                 
434                 if ((game.skill < 3) &&  (strstr(objective->description, "L.R.T.S.")) && (!gameData.completedWorld))
435                 {
436                         graphics.drawString(_("???? ???????? ????"), col1, y, TXT_LEFT, panel);
437                 }
438                 else
439                 {
440                         graphics.drawString(_(objective->description), col1, y, TXT_LEFT, panel);
441                 }
442                 
443                 // this is a fake objective (for the 4th Ancient Tomb)
444                 if (objective->targetValue == -1)
445                 {
446                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
447                         graphics.drawString(_("Incomplete"), col2, y, TXT_RIGHT, panel);
448                 }
449                 else if (objective->currentValue < objective->targetValue)
450                 {
451                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
452                         if (objective->targetValue == 1)
453                         {
454                                 graphics.drawString(_("Incomplete"), col2, y, TXT_RIGHT, panel);
455                         }
456                         else
457                         {
458                                 snprintf(message, sizeof message, "%d / %d", objective->currentValue, objective->targetValue);
459                                 graphics.drawString(message, col2, y, TXT_RIGHT, panel);
460                         }
461                 }
462                 else
463                 {
464                         graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
465                         graphics.drawString(_("Completed"), col2, y, TXT_RIGHT, panel);
466                 }
467         }
468         
469         if (game.skill == 3)
470         {
471                 graphics.setFontColor(0xff, 0xff, 0x00, 0x00, 0x00, 0x00);
472                 snprintf(message, sizeof message, _("Time Limit - %d:%.2d Minutes"), map.remainingMinutes, map.remainingSeconds);
473                 graphics.drawString(message, 200, 260, TXT_CENTERED, panel);
474         }
475         
476         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
477         graphics.drawString(_("Press Fire to Continue"), 200, 280, TXT_CENTERED, panel);
478
479         engine.flushInput();
480         engine.clearInput();
481
482         int px, py;
483
484         map.getRandomEntityPosition(&px, &py);
485         map.getRandomEntityPosition(&player.tx, &player.ty);
486
487         player.x = px;
488         player.y = py;
489
490         unsigned int frameLimit = SDL_GetTicks() + 16;
491                 
492         while (true)
493         {
494                 if ((int)player.x < player.tx) player.x += 2;
495                 if ((int)player.x > player.tx) player.x -= 2;
496                 if ((int)player.y < player.ty) player.y += 2;
497                 if ((int)player.y > player.ty) player.y -= 2;
498
499                 if (Collision::collision(player.x, player.y, 5, 5, player.tx, player.ty, 5, 5))
500                         map.getRandomEntityPosition(&player.tx, &player.ty);
501
502                 engine.setPlayerPosition((int)player.x, (int)player.y, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
503
504                 doGameStuff();
505                 drawMapTopLayer();
506                 graphics.blit(panelBack, 320, 220, graphics.screen, true);
507                 graphics.blit(panel, 320, 220, graphics.screen, true);
508
509                 engine.delay(frameLimit);
510                 frameLimit = SDL_GetTicks() + 16;
511
512                 if (engine.userAccepts())
513                         break;
514         }
515
516         SDL_FreeSurface(panel);
517         SDL_FreeSurface(panelBack);
518
519         SDL_FillRect(graphics.screen, NULL, graphics.black);
520         graphics.delay(1000);
521 }
522
523 void beamInPlayer()
524 {
525         game.getCheckPoint(&player.x, &player.y);
526         
527         int beamInTime = 180;
528         
529         unsigned int frameLimit = SDL_GetTicks() + 16;
530         
531         audio.playSound(SND_TELEPORT1, CH_ANY);
532         
533         engine.setPlayerPosition((int)player.x, (int)player.y, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
534         
535         while (beamInTime > 0)
536         {
537                 engine.delay(frameLimit);
538                 frameLimit = SDL_GetTicks() + 16;
539                 
540                 doGameStuff();
541                 drawMapTopLayer();
542                 
543                 if ((beamInTime % 10) == 0)
544                         addTeleportParticles(player.x + 10, player.y + 10, 50, -1);
545                 
546                 beamInTime--;
547         }
548         
549         game.getCheckPoint(&player.x, &player.y);
550         
551         player.dx = 0;
552         player.dy = 0;
553         player.immune = 120;
554         player.environment = ENV_AIR;
555         player.oxygen = 7;
556         player.fuel = 7;
557         Math::removeBit(&player.flags, ENT_FLIES);
558 }
559
560 int doGame()
561 {
562         graphics.setFontSize(0);
563
564         SDL_FillRect(graphics.screen, NULL, graphics.black);
565         graphics.delay(1000);
566
567         Uint32 then, frames, frameLimit, millis;
568         Uint32 start, cur;
569
570         #if DEBUG
571         Uint32 now, frameCounter;
572         char fps[10];
573         strlcpy(fps, "fps", sizeof fps);
574         #endif
575
576         engine.messageTime = -1;
577         engine.messagePriority = -1;
578
579         audio.playMusic();
580         audio.playAmbiance();
581
582         if (!game.continueFromCheckPoint)
583         {
584                 player.health = -99;
585
586                 if ((!map.isBossMission) && (replayData.replayMode == REPLAY_MODE::NONE))
587                 {
588                         showMissionInformation();
589                 }
590
591                 game.levelsStarted++;
592         }
593         else
594         {
595                 game.useObjectiveCheckPoint();
596         }
597
598         player.setVelocity(0, 1);
599         player.baseThink = 60;
600         player.health = MAX_HEALTH;
601
602         if (game.continueFromCheckPoint)
603         {
604                 player.health = (MAX_HEALTH / 2);
605                 player.setSprites(graphics.getSprite("BobRight", true), graphics.getSprite("BobLeft", true), graphics.getSprite("BobSpin", true));
606         }
607         else
608         {
609                 player.currentWeapon = &weapon[WP_PISTOL];
610         }
611
612         game.resetMissionOver();
613
614         frameLimit = SDL_GetTicks() + 16;
615         frames = millis = 0;
616         start = then = SDL_GetTicks();
617 #ifdef DEBUG
618         frameCounter = SDL_GetTicks();
619 #endif
620
621         if ((strcmp(map.name, "Space Station") == 0) && (!game.continueFromCheckPoint))
622         {
623                 beamInPlayer();
624         }
625         else
626         {
627                 resetPlayer();
628         }
629
630         engine.flushInput();
631         engine.clearInput();
632
633         debug(("Map Clipping is %d %d %d %d\n", map.limitLeft, map.limitRight, map.limitUp, map.limitDown));
634
635         game.continueFromCheckPoint = false;
636
637         engine.paused = false;
638
639         while (true)
640         {
641                 ++frames;
642                 ++millis;
643                 cur = SDL_GetTicks();
644
645                 if (game.missionOverReason != MIS_PLAYEROUT)
646                 {
647                         engine.setPlayerPosition((int)player.x, (int)player.y, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
648                 }
649
650                 doSpawnPoints();
651                 doGameStuff();
652
653                 doPlayer();
654                 raiseWaterLevel();
655
656                 if ((player.environment == ENV_SLIME) || (player.environment == ENV_LAVA) || (player.health < 1))
657                 {
658                         if (player.health < 1)
659                         {
660                                 game.setMissionOver(MIS_PLAYERDEAD);
661                                 audio.fadeMusic();
662                                 audio.stopAmbiance();
663                         }
664                         else
665                         {
666                                 game.setMissionOver(MIS_PLAYEROUT);
667                                 player.immune = 130;
668                         }
669                 }
670
671                 if (config.isControl(CONTROL::MAP))
672                 {
673                         if (!map.isBossMission)
674                         {
675                                 showMap((int)(player.x / 32), (int)(player.y / 32));
676                         }
677                         else
678                         {
679                                 engine.setInfoMessage("Automap is not available!", 1, INFO_HINT);
680                         }
681                 }
682
683                 drawMapTopLayer();
684                 doStatusBar();
685                 doMusicInfo(cur - start);
686
687                 if ((engine.keyState[SDL_SCANCODE_ESCAPE]) && (game.missionOver == 0))
688                 {
689                         if (replayData.replayMode == REPLAY_MODE::NONE)
690                         {
691                                 showInGameOptions();
692                         }
693                         else
694                         {
695                                 exit(0);
696                         }
697                 }
698
699                 if (allObjectivesCompleted())
700                 {
701                         if (game.missionOver == 0)
702                         {
703                                 if (map.isBossMission)
704                                 {
705                                         map.killAllEnemies();
706                                 }
707                                 
708                                 audio.stopMusic();
709                                 audio.stopAmbiance();
710
711                                 game.setMissionOver(MIS_COMPLETE);
712                                 engine.setInfoMessage("All Required Objectives Met - Mission Complete", 10, INFO_OBJECTIVE);
713                         }
714                 }
715
716                 if (game.missionOver > 0)
717                 {
718                         game.missionOver--;
719                 
720                         if (game.missionOver == 0)
721                         {
722                                 if (game.missionOverReason == MIS_PLAYEROUT)
723                                 {
724                                         SDL_FillRect(graphics.screen, NULL, graphics.black);
725                                         graphics.updateScreen();
726                                         graphics.delay(1000);
727                                         engine.flushInput();
728                                         engine.clearInput();
729                                         resetPlayer();
730                                         game.resetMissionOver();
731                                 }
732                                 else
733                                 {
734                                         if (game.missionOverReason == MIS_COMPLETE)
735                                         {
736                                                 game.missionOver = MAX_FPS * 2;
737                                                 
738                                                 if (strcmp(map.name, "Space Station") != 0)
739                                                 {
740                                                         addTeleportParticles(player.x, player.y, 50, SND_TELEPORT3);
741                                                         dropCarriedItems();
742                                                         game.missionOverReason = MIS_PLAYERESCAPE;
743                                                 }
744                                                 else
745                                                 {
746                                                         break;
747                                                 }
748                                         }
749                                         else if (game.missionOverReason == MIS_GAMECOMPLETE)
750                                         {
751                                                 addTeleportParticles(player.x, player.y, 50, SND_TELEPORT3);
752                                                 game.missionOverReason = MIS_PLAYERESCAPE;
753                                                 game.missionOver = MAX_FPS * 4;
754                                         }
755                                         else
756                                         {
757                                                 if (replayData.replayMode != REPLAY_MODE::NONE)
758                                                 {
759                                                         exit(0);
760                                                 }
761                                         
762                                                 break;
763                                         }
764                                 }
765                         }
766                 }
767
768                 Math::limitInt(&(--game.lastComboTime), 0, 60);
769
770                 if (millis >= 60)
771                 {
772                         millis = 0;
773                         
774                         if ((game.missionOverReason == MIS_INPROGRESS) || (game.missionOverReason == MIS_PLAYEROUT))
775                         {
776                                 game.incrementMissionTime();
777                                 
778                                 if (game.skill == 3)
779                                 {
780                                         doTimeRemaining();
781                                 }
782                         }
783                 }
784
785                 if (engine.paused)
786                 {
787                         doPauseInfo();
788                         audio.pause();
789                 }
790
791                 while (engine.paused)
792                 {
793                         engine.getInput();
794                         config.populate();
795                         config.doPause();
796                         graphics.updateScreen();
797                         then = SDL_GetTicks();
798                         frames = 0;
799
800                         if (!engine.paused)
801                         {
802                                 audio.resume();
803                         }
804
805                         SDL_Delay(16);
806                 }
807                 
808                 if ((engine.keyState[SDL_SCANCODE_F3]) && (engine.cheatSkipLevel))
809                 {
810                         autoCompleteAllObjectives(true);
811                         engine.keyState[SDL_SCANCODE_F3] = 0;
812                         engine.setInfoMessage("Skipping Mission...", 2, INFO_OBJECTIVE);
813                 }
814                 
815                 #if DEBUG
816                 if (engine.keyState[SDL_SCANCODE_F1])
817                 {
818                         autoCompleteAllObjectives(false);
819                 }               
820                 #endif
821                 
822                 if (replayData.replayMode != REPLAY_MODE::PLAYBACK)
823                 {
824                         engine.delay(frameLimit);
825                 }
826                 else if (!replayData.fast)
827                 {
828                         engine.delay(frameLimit);
829                 }
830                 
831                 if (engine.keyState[SDL_SCANCODE_F5])
832                 {
833                         replayData.fast = !replayData.fast;
834                         engine.keyState[SDL_SCANCODE_F5] = 0;
835                 }
836                 
837                 frameLimit = SDL_GetTicks()  + 16;
838                 
839                 if (game.missionOverReason == MIS_GAMECOMPLETE)
840                         frameLimit = SDL_GetTicks() + 64;
841
842                 #if DEBUG
843                 static Graphics::SurfaceCache fpsCache;
844                 graphics.drawString(fps, 600, 30, true, graphics.screen, fpsCache);
845
846                 if (SDL_GetTicks() > frameCounter + 500)
847                 {
848                         now = SDL_GetTicks();
849                         snprintf(fps, sizeof fps, "%2.2f fps", ((double)frames*1000)/(now - then));
850                         then = frameCounter = SDL_GetTicks();
851                         frames = 0;
852                 }
853                 #endif
854         }
855
856         if (allObjectivesCompleted())
857         {
858                 if (strcmp(map.name, "Final Battle") == 0)
859                 {
860                         game.missionOverReason = MIS_GAMECOMPLETE;
861                 }
862                 else
863                 {
864                         game.missionOverReason = MIS_COMPLETE;
865                 }
866         }
867
868         switch (game.missionOverReason)
869         {
870                 case MIS_COMPLETE:
871                         if (strcmp(map.name, "Space Station"))
872                         {
873                                 graphics.delay(1000);
874                                 audio.loadMusic("music/grasslands");
875                                 audio.playMusic();
876                                 graphics.fadeToBlack();
877                                 
878                                 bool previouslyCompleted = gameData.stagePreviouslyCleared(game.stageName);
879                                 
880                                 showMissionClear();
881                                 
882                                 if (engine.practice)
883                                 {
884                                         return SECTION_TITLE;
885                                 }
886                                 
887                                 if (!previouslyCompleted)
888                                 {
889                                         checkEndCutscene();
890                                 }
891                                 return SECTION_HUB;
892                         }
893                         else
894                         {
895                                 graphics.fadeToBlack();
896                                 processPostMissionData();
897                                 saveGame();
898                                 game.setMapName("data/finalBattle");
899                                 game.setStageName("Final Battle");
900                                 return SECTION_GAME;
901                         }
902                         break;
903                         
904                 case MIS_GAMECOMPLETE:
905                         SDL_FillRect(graphics.screen, NULL, graphics.white);
906                         graphics.updateScreen();
907                         graphics.fadeToBlack();
908                         
909                         // we've finished the game. Extreme mode is now available! :)
910                         engine.extremeAvailable = true;
911                         map.clear();
912                         graphics.free();
913                         audio.free();
914                         checkEndCutscene();
915                         return SECTION_CREDITS;
916                         break;
917
918                 case MIS_TIMEUP:
919                         game.canContinue = 0;
920                 case MIS_PLAYERDEAD:
921                         if (player.health > -60)
922                         {
923                                 player.health = -99;
924                                 gibPlayer();
925                         }
926                         return SECTION_GAMEOVER;
927                         break;
928
929                 case MIS_PLAYERESCAPE:
930                         game.escapes++;
931                         if (gameData.stagePreviouslyCleared(game.stageName))
932                         {
933                                 processPostMissionData();
934                                 saveGame();
935                         }
936                         return SECTION_HUB;
937                         break;
938                         
939                 case MIS_PLAYERRESTART:
940                         clearAllMissionData();
941                         return SECTION_GAME;
942                         break;
943
944                 default:
945                         return SECTION_TITLE;
946                         break;
947         }
948
949         return SECTION_TITLE;
950 }