2 Copyright (C) 2004-2011 Parallel Realities
3 Copyright (C) 2011-2015 Perpendicular Dimensions
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 2
8 of the License, or (at your option) any later version.
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.
14 See the GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 map.persistantList.clear();
29 engine.practice = false;
31 game.skill = engine.skill;
34 void showInGameOptions()
36 if (!engine.loadWidgets(_("data/inGameWidgets")))
38 graphics.showErrorAndExit(ERR_FILE, _("data/inGameWidgets"));
41 graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
43 int cont, options, escape, quit, escapeyes, escapeno, warnno, warnyes, quitno, quityes, train, trainno, trainyes, restart, restartno, restartyes;
44 cont = options = escape = quit = escapeyes = escapeno = warnno = warnyes = quitno = quityes = train = trainno = trainyes = restart = restartno = restartyes = 0;
46 engine.setWidgetVariable("continue", &cont);
47 engine.setWidgetVariable("options", &options);
48 engine.setWidgetVariable("escape", &escape);
49 engine.setWidgetVariable("restart", &restart);
50 engine.setWidgetVariable("quit", &quit);
51 engine.setWidgetVariable("train", &train);
53 engine.setWidgetVariable("warnno", &warnno);
54 engine.setWidgetVariable("warnyes", &warnyes);
56 engine.setWidgetVariable("restartno", &restartno);
57 engine.setWidgetVariable("restartyes", &restartyes);
59 engine.setWidgetVariable("quitno", &quitno);
60 engine.setWidgetVariable("quityes", &quityes);
62 engine.setWidgetVariable("trainno", &quitno);
63 engine.setWidgetVariable("trainyes", &quityes);
65 engine.setWidgetVariable("escapeno", &escapeno);
66 engine.setWidgetVariable("escapeyes", &escapeyes);
68 engine.showWidgetGroup("warning", false);
69 engine.showWidgetGroup("restartconf", false);
70 engine.showWidgetGroup("escapeconf", false);
71 engine.showWidgetGroup("quitconf", false);
72 engine.showWidgetGroup("trainconf", false);
74 if ((map.isBossMission) || (engine.practice) || (strcmp(map.name, "Space Station") == 0))
76 engine.enableWidget("escape", false);
77 engine.enableWidget("restart", false);
82 engine.showWidget("train", false);
86 engine.showWidget("quit", false);
93 audio.playMenuSound(2);
99 graphics.updateScreen();
103 if ((config.isControl(CONTROL::PAUSE)) || (engine.keyState[SDL_SCANCODE_ESCAPE]))
105 engine.keyState[SDL_SCANCODE_ESCAPE] = 0;
106 config.resetControl(CONTROL::PAUSE);
110 menuSound = engine.processWidgets();
114 graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
116 audio.playMenuSound(menuSound);
126 engine.showWidgetGroup("options", false);
128 if (!gameData.stagePreviouslyCleared(game.stageName))
130 engine.showWidgetGroup("warning", true);
131 engine.highlightWidget("warnno");
135 engine.showWidgetGroup("escapeconf", true);
136 engine.highlightWidget("escapeno");
139 graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
144 if ((escapeyes) || (warnyes))
147 audio.stopAmbiance();
148 addTeleportParticles(player.x, player.y, 50, SND_TELEPORT3);
150 game.setMissionOver(MIS_PLAYERESCAPE);
160 if ((warnno) || (quitno) || (escapeno) || (trainno) || (restartno))
162 engine.highlightWidget("continue");
163 engine.showWidgetGroup("options", true);
164 engine.showWidgetGroup("warning", false);
165 engine.showWidgetGroup("trainconf", false);
166 engine.showWidgetGroup("escapeconf", false);
167 engine.showWidgetGroup("quitconf", false);
168 engine.showWidgetGroup("restartconf", false);
170 if (!engine.practice)
172 engine.showWidget("train", false);
176 engine.showWidget("quit", false);
179 graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
181 quitno = trainno = warnno = escapeno = restartno = 0;
186 engine.showWidgetGroup("options", false);
187 engine.showWidgetGroup("quitconf", true);
188 engine.highlightWidget("quitno");
190 graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
197 engine.showWidgetGroup("options", false);
198 engine.showWidgetGroup("trainconf", true);
199 engine.highlightWidget("trainno");
201 graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
208 engine.showWidgetGroup("options", false);
209 engine.showWidgetGroup("restartconf", true);
210 engine.highlightWidget("restartno");
212 graphics.drawRect(120, 100, 400, 300, graphics.black, graphics.white, graphics.screen);
217 if ((quityes) || (trainyes))
219 game.setMissionOver(MIS_PLAYERQUIT);
225 game.setMissionOver(MIS_PLAYERRESTART);
226 SDL_FillRect(graphics.screen, NULL, graphics.black);
228 audio.stopAmbiance();
241 replayData.read(config.command);
243 if (game.missionOverReason == MIS_INPROGRESS)
248 engine.doFrameLoop();
250 graphics.updateScreen();
251 graphics.animateSprites();
252 graphics.drawBackground();
264 if (map.isBossMission)
273 if (map.isBlizzardLevel)
280 replayData.set(config.command);
287 audio.stopAmbiance();
289 if (!engine.loadWidgets(_("data/gameOverWidgets")))
291 graphics.showErrorAndExit(ERR_FILE, _("data/gameOverWidgets"));
294 SDL_Surface *gameover = graphics.quickSprite("Game Over", graphics.loadImage("gfx/main/gameover.png"));
295 graphics.setTransparent(gameover);
297 audio.loadGameOverMusic();
303 unsigned int frameLimit = SDL_GetTicks() + 16;
305 bool showGameOverOptions = false;
306 int cont, quit, menuSound;
307 cont = quit = menuSound = 0;
309 engine.setWidgetVariable("gameOverNo", &cont);
310 engine.setWidgetVariable("gameOverYes", &quit);
312 if (game.canContinue > 1)
314 Widget *widget = engine.getWidgetByName("gameOverNo");
316 snprintf(postfix, sizeof postfix, " (%d)", game.canContinue);
317 strlcat(widget->label, postfix, sizeof widget->label);
323 audio.playMenuSound(menuSound);
328 graphics.blit(gameover, 320, 240, graphics.screen, true);
330 if (engine.userAccepts())
332 if (!showGameOverOptions)
334 showGameOverOptions = true;
335 engine.showWidgetGroup("gameover", true);
336 engine.highlightWidget("gameOverNo");
341 // Can't continue on a boss mission or if no checkpoints reached!
342 if ((map.isBossMission) || (!game.canContinue))
344 engine.showWidgetGroup("gameover", false);
349 if (showGameOverOptions)
352 menuSound = engine.processWidgets();
355 if ((cont) || (quit))
358 engine.delay(frameLimit);
359 frameLimit = SDL_GetTicks() + 16;
365 graphics.fadeToBlack();
368 return SECTION_TITLE;
371 game.continueFromCheckPoint = true;
373 audio.reloadLevelMusic();
378 void showMissionInformation()
380 SDL_FillRect(graphics.screen, NULL, graphics.black);
381 graphics.updateScreen();
383 SDL_Surface *panel = graphics.createSurface(400, 300);
384 SDL_Surface *panelBack = graphics.alphaRect(400, 300, 0x00, 0x00, 0x00);
385 SDL_SetColorKey(panel, SDL_TRUE, SDL_MapRGB(panel->format, 0, 0, 0));
387 graphics.drawRect(1, 1, 398, 298, graphics.black, graphics.white, panelBack);
394 Objective *objective;
396 graphics.setFontSize(0);
398 graphics.setFontSize(3);
399 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
400 graphics.drawString(_(game.stageName), 200, 20, TXT_CENTERED, panel);
402 graphics.setFontSize(0);
406 if (map.totalMIAs > 0)
408 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
409 snprintf(message, sizeof message, _("Rescue %d MIAs"), map.requiredMIAs);
410 graphics.drawString(message, col1, y, TXT_LEFT, panel);
412 if (map.foundMIAs < map.requiredMIAs)
414 graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
415 snprintf(message, sizeof message, "%d / %d", map.foundMIAs, map.requiredMIAs);
416 graphics.drawString(message, col2, y, TXT_RIGHT, panel);
420 graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
421 graphics.drawString(_("Completed"), col2, y, TXT_RIGHT, panel);
425 objective = (Objective*)map.objectiveList.getHead();
427 while (objective->next != NULL)
429 objective = (Objective*)objective->next;
433 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
435 if ((game.skill < 3) && (strstr(objective->description, "L.R.T.S.")) && (!gameData.completedWorld))
437 graphics.drawString(_("???? ???????? ????"), col1, y, TXT_LEFT, panel);
441 graphics.drawString(_(objective->description), col1, y, TXT_LEFT, panel);
444 // this is a fake objective (for the 4th Ancient Tomb)
445 if (objective->targetValue == -1)
447 graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
448 graphics.drawString(_("Incomplete"), col2, y, TXT_RIGHT, panel);
450 else if (objective->currentValue < objective->targetValue)
452 graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
453 if (objective->targetValue == 1)
455 graphics.drawString(_("Incomplete"), col2, y, TXT_RIGHT, panel);
459 snprintf(message, sizeof message, "%d / %d", objective->currentValue, objective->targetValue);
460 graphics.drawString(message, col2, y, TXT_RIGHT, panel);
465 graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
466 graphics.drawString(_("Completed"), col2, y, TXT_RIGHT, panel);
472 graphics.setFontColor(0xff, 0xff, 0x00, 0x00, 0x00, 0x00);
473 snprintf(message, sizeof message, _("Time Limit - %d:%.2d Minutes"), map.remainingMinutes, map.remainingSeconds);
474 graphics.drawString(message, 200, 260, TXT_CENTERED, panel);
477 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
478 graphics.drawString(_("Press Fire to Continue"), 200, 280, TXT_CENTERED, panel);
485 map.getRandomEntityPosition(&px, &py);
486 map.getRandomEntityPosition(&player.tx, &player.ty);
491 unsigned int frameLimit = SDL_GetTicks() + 16;
495 if ((int)player.x < player.tx) player.x += 2;
496 if ((int)player.x > player.tx) player.x -= 2;
497 if ((int)player.y < player.ty) player.y += 2;
498 if ((int)player.y > player.ty) player.y -= 2;
500 if (Collision::collision(player.x, player.y, 5, 5, player.tx, player.ty, 5, 5))
501 map.getRandomEntityPosition(&player.tx, &player.ty);
503 engine.setPlayerPosition((int)player.x, (int)player.y, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
507 graphics.blit(panelBack, 320, 220, graphics.screen, true);
508 graphics.blit(panel, 320, 220, graphics.screen, true);
510 engine.delay(frameLimit);
511 frameLimit = SDL_GetTicks() + 16;
513 if (engine.userAccepts())
517 SDL_FreeSurface(panel);
518 SDL_FreeSurface(panelBack);
520 SDL_FillRect(graphics.screen, NULL, graphics.black);
521 graphics.delay(1000);
526 game.getCheckPoint(&player.x, &player.y);
528 int beamInTime = 180;
530 unsigned int frameLimit = SDL_GetTicks() + 16;
532 audio.playSound(SND_TELEPORT1, CH_ANY);
534 engine.setPlayerPosition((int)player.x, (int)player.y, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
536 while (beamInTime > 0)
538 engine.delay(frameLimit);
539 frameLimit = SDL_GetTicks() + 16;
544 if ((beamInTime % 10) == 0)
545 addTeleportParticles(player.x + 10, player.y + 10, 50, -1);
550 game.getCheckPoint(&player.x, &player.y);
555 player.environment = ENV_AIR;
558 Math::removeBit(&player.flags, ENT_FLIES);
563 graphics.setFontSize(0);
565 SDL_FillRect(graphics.screen, NULL, graphics.black);
566 graphics.delay(1000);
568 Uint32 then, frames, frameLimit, millis;
572 Uint32 now, frameCounter;
574 strlcpy(fps, "fps", sizeof fps);
577 engine.messageTime = -1;
578 engine.messagePriority = -1;
581 audio.playAmbiance();
583 if (!game.continueFromCheckPoint)
587 if ((!map.isBossMission) && (replayData.replayMode == REPLAY_MODE::NONE))
589 showMissionInformation();
592 game.levelsStarted++;
596 game.useObjectiveCheckPoint();
599 player.setVelocity(0, 1);
600 player.baseThink = 60;
601 player.health = MAX_HEALTH;
603 if (game.continueFromCheckPoint)
605 player.health = (MAX_HEALTH / 2);
606 player.setSprites(graphics.getSprite("BobRight", true), graphics.getSprite("BobLeft", true), graphics.getSprite("BobSpin", true));
610 player.currentWeapon = &weapon[WP_PISTOL];
613 game.resetMissionOver();
615 frameLimit = SDL_GetTicks() + 16;
617 start = then = SDL_GetTicks();
619 frameCounter = SDL_GetTicks();
622 if ((strcmp(map.name, "Space Station") == 0) && (!game.continueFromCheckPoint))
634 debug(("Map Clipping is %d %d %d %d\n", map.limitLeft, map.limitRight, map.limitUp, map.limitDown));
636 game.continueFromCheckPoint = false;
638 engine.paused = false;
644 cur = SDL_GetTicks();
646 if (game.missionOverReason != MIS_PLAYEROUT)
648 engine.setPlayerPosition((int)player.x, (int)player.y, map.limitLeft, map.limitRight, map.limitUp, map.limitDown);
657 if ((player.environment == ENV_SLIME) || (player.environment == ENV_LAVA) || (player.health < 1))
659 if (player.health < 1)
661 game.setMissionOver(MIS_PLAYERDEAD);
663 audio.stopAmbiance();
667 game.setMissionOver(MIS_PLAYEROUT);
672 if (config.isControl(CONTROL::MAP))
674 if (!map.isBossMission)
676 showMap((int)(player.x / 32), (int)(player.y / 32));
680 engine.setInfoMessage("Automap is not available!", 1, INFO_HINT);
686 doMusicInfo(cur - start);
688 if ((engine.keyState[SDL_SCANCODE_ESCAPE]) && (game.missionOver == 0))
690 if (replayData.replayMode == REPLAY_MODE::NONE)
700 if (allObjectivesCompleted())
702 if (game.missionOver == 0)
704 if (map.isBossMission)
706 map.killAllEnemies();
710 audio.stopAmbiance();
712 game.setMissionOver(MIS_COMPLETE);
713 engine.setInfoMessage("All Required Objectives Met - Mission Complete", 10, INFO_OBJECTIVE);
717 if (game.missionOver > 0)
721 if (game.missionOver == 0)
723 if (game.missionOverReason == MIS_PLAYEROUT)
725 SDL_FillRect(graphics.screen, NULL, graphics.black);
726 graphics.updateScreen();
727 graphics.delay(1000);
731 game.resetMissionOver();
735 if (game.missionOverReason == MIS_COMPLETE)
737 game.missionOver = MAX_FPS * 2;
739 if (strcmp(map.name, "Space Station") != 0)
741 addTeleportParticles(player.x, player.y, 50, SND_TELEPORT3);
743 game.missionOverReason = MIS_PLAYERESCAPE;
750 else if (game.missionOverReason == MIS_GAMECOMPLETE)
752 addTeleportParticles(player.x, player.y, 50, SND_TELEPORT3);
753 game.missionOverReason = MIS_PLAYERESCAPE;
754 game.missionOver = MAX_FPS * 4;
758 if (replayData.replayMode != REPLAY_MODE::NONE)
769 Math::limitInt(&(--game.lastComboTime), 0, 60);
775 if ((game.missionOverReason == MIS_INPROGRESS) || (game.missionOverReason == MIS_PLAYEROUT))
777 game.incrementMissionTime();
792 while (engine.paused)
797 graphics.updateScreen();
798 then = SDL_GetTicks();
809 if ((engine.keyState[SDL_SCANCODE_F3]) && (engine.cheatSkipLevel))
811 autoCompleteAllObjectives(true);
812 engine.keyState[SDL_SCANCODE_F3] = 0;
813 engine.setInfoMessage("Skipping Mission...", 2, INFO_OBJECTIVE);
817 if (engine.keyState[SDL_SCANCODE_F1])
819 autoCompleteAllObjectives(false);
823 if (replayData.replayMode != REPLAY_MODE::PLAYBACK)
825 engine.delay(frameLimit);
827 else if (!replayData.fast)
829 engine.delay(frameLimit);
832 if (engine.keyState[SDL_SCANCODE_F5])
834 replayData.fast = !replayData.fast;
835 engine.keyState[SDL_SCANCODE_F5] = 0;
838 frameLimit = SDL_GetTicks() + 16;
840 if (game.missionOverReason == MIS_GAMECOMPLETE)
841 frameLimit = SDL_GetTicks() + 64;
844 static Graphics::SurfaceCache fpsCache;
845 graphics.drawString(fps, 600, 30, true, graphics.screen, fpsCache);
847 if (SDL_GetTicks() > frameCounter + 500)
849 now = SDL_GetTicks();
850 snprintf(fps, sizeof fps, "%2.2f fps", ((double)frames*1000)/(now - then));
851 then = frameCounter = SDL_GetTicks();
857 if (allObjectivesCompleted())
859 if (strcmp(map.name, "Final Battle") == 0)
861 game.missionOverReason = MIS_GAMECOMPLETE;
865 game.missionOverReason = MIS_COMPLETE;
869 switch (game.missionOverReason)
872 if (strcmp(map.name, "Space Station"))
874 graphics.delay(1000);
875 audio.loadMusic("music/grasslands");
877 graphics.fadeToBlack();
879 bool previouslyCompleted = gameData.stagePreviouslyCleared(game.stageName);
885 return SECTION_TITLE;
888 if (!previouslyCompleted)
896 graphics.fadeToBlack();
897 processPostMissionData();
899 game.setMapName("data/finalBattle");
900 game.setStageName("Final Battle");
905 case MIS_GAMECOMPLETE:
906 SDL_FillRect(graphics.screen, NULL, graphics.white);
907 graphics.updateScreen();
908 graphics.fadeToBlack();
910 // we've finished the game. Extreme mode is now available! :)
911 engine.extremeAvailable = true;
916 return SECTION_CREDITS;
920 game.canContinue = 0;
922 if (player.health > -60)
927 return SECTION_GAMEOVER;
930 case MIS_PLAYERESCAPE:
932 if (gameData.stagePreviouslyCleared(game.stageName))
934 processPostMissionData();
940 case MIS_PLAYERRESTART:
941 clearAllMissionData();
946 return SECTION_TITLE;
950 return SECTION_TITLE;