2 Copyright (C) 2004-2011 Parallel Realities
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.
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.
13 See the GNU General Public License for more details.
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.
23 extern void doMusicInfo(unsigned int);
25 void createStatsPanel(int page)
27 SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
29 graphics.drawRect(1, 1, image->w - 2, image->h - 2, graphics.black, graphics.white, image);
37 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
39 graphics.drawString(_("Metal Blob Solid : Statistics"), 200, y, true, image);
42 Sprite *arrows = graphics.getSprite("HubArrows", true);
47 graphics.drawString(_("Skill Level:"), x1, y += 20, false, image);
48 snprintf(string, sizeof string, "%s", _(skill[game.skill]));
49 graphics.drawString(string, x2, y, false, image);
51 graphics.drawString(_("Score:"), x1, y += 20, false, image);
52 snprintf(string, sizeof string, "%d", game.score);
53 graphics.drawString(string, x2, y, false, image);
55 graphics.drawString(_("MIAs Saved:"), x1, y += 20, false, image);
56 snprintf(string, sizeof string, "%d", game.totalMIAsRescued);
57 graphics.drawString(string, x2, y, false, image);
59 graphics.drawString(_("Objectives Completed:"), x1, y += 20, false, image);
60 snprintf(string, sizeof string, "%d", game.totalObjectivesCompleted);
61 graphics.drawString(string, x2, y, false, image);
63 // Don't do this on Extreme or it will always say 100%
66 graphics.drawString(_("Percentage Complete:"), x1, y += 20, false, image);
67 snprintf(string, sizeof string, "%d%%", gameData.getPercentageComplete());
68 graphics.drawString(string, x2, y, false, image);
71 snprintf(string, sizeof string, "%s - %.2d:%.2d:%.2d", _("Total Game Time"), game.totalHours, game.totalMinutes, game.totalSeconds);
72 graphics.drawString(string, 200, y += 110, true, image);
78 graphics.drawString(_("Enemies Defeated:"), x1, y += 20, false, image);
79 snprintf(string, sizeof string, "%d", game.totalEnemiesDefeated);
80 graphics.drawString(string, x2, y, false, image);
82 graphics.drawString(_("Items Collected:"), x1, y += 20, false, image);
83 snprintf(string, sizeof string, "%d", game.totalItemsCollected);
84 graphics.drawString(string, x2, y, false, image);
86 graphics.drawString(_("Bonuses Picked Up:"), x1, y += 20, false, image);
87 snprintf(string, sizeof string, "%d", game.totalBonusesCollected);
88 graphics.drawString(string, x2, y, false, image);
90 graphics.drawString(_("Best Combo:"), x1, y += 20, false, image);
91 snprintf(string, sizeof string, _("%d Hits"), game.maxComboHits);
92 graphics.drawString(string, x2, y, false, image);
94 graphics.drawString(_("Missions Started:"), x1, y += 20, false, image);
95 snprintf(string, sizeof string, "%d", game.levelsStarted);
96 graphics.drawString(string, x2, y, false, image);
98 graphics.drawString(_("Continues Used:"), x1, y += 20, false, image);
99 snprintf(string, sizeof string, "%d", game.continuesUsed);
100 graphics.drawString(string, x2, y, false, image);
102 if ((game.continuesUsed > 0) && (game.levelsStarted > 0))
104 graphics.drawString(_("Average Continue Usage:"), x1, y += 20, false, image);
105 snprintf(string, sizeof string, "%d", (game.continuesUsed / game.levelsStarted));
106 graphics.drawString(string, x2, y, false, image);
109 graphics.drawString(_("Escapes Used:"), x1, y += 20, false, image);
110 snprintf(string, sizeof string, "%d", game.escapes);
111 graphics.drawString(string, x2, y, false, image);
121 graphics.drawString(_("Weapon"), x1, y += 20, false, image);
122 graphics.drawString(_("Ammo Used"), x2, y, false, image);
123 graphics.drawString(_("Accuracy"), x3, y, false, image);
125 graphics.drawString(_("Pistol"), x1, y += 30, false, image);
126 snprintf(string, sizeof string, "%d", game.bulletsFired[WP_PISTOL]);
127 graphics.drawString(string, x2, y, false, image);
128 snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_PISTOL));
129 graphics.drawString(string, x3, y, false, image);
131 graphics.drawString(_("Machine Gun"), x1, y += 20, false, image);
132 snprintf(string, sizeof string, "%d", game.bulletsFired[WP_MACHINEGUN]);
133 graphics.drawString(string, x2, y, false, image);
134 snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_MACHINEGUN));
135 graphics.drawString(string, x3, y, false, image);
137 graphics.drawString(_("Laser Cannon"), x1, y += 20, false, image);
138 snprintf(string, sizeof string, "%d", game.bulletsFired[WP_LASER]);
139 graphics.drawString(string, x2, y, false, image);
140 snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_LASER));
141 graphics.drawString(string, x3, y, false, image);
143 graphics.drawString(_("Grenades"), x1, y += 20, false, image);
144 snprintf(string, sizeof string, "%d", game.bulletsFired[WP_GRENADES]);
145 graphics.drawString(string, x2, y, false, image);
146 snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_GRENADES));
147 graphics.drawString(string, x3, y, false, image);
149 graphics.drawString(_("Spread Gun"), x1, y += 20, false, image);
150 snprintf(string, sizeof string, "%d", game.bulletsFired[WP_SPREAD]);
151 graphics.drawString(string, x2, y, false, image);
152 snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_SPREAD));
153 graphics.drawString(string, x3, y, false, image);
155 graphics.drawString(_("Total"), x1, y += 30, false, image);
156 snprintf(string, sizeof string, "%d", game.getTotalBulletsFired());
157 graphics.drawString(string, x2, y, false, image);
158 snprintf(string, sizeof string, "%d%%", game.getTotalAccuracy());
159 graphics.drawString(string, x3, y, false, image);
161 snprintf(string, sizeof string, "%s - %s", _("Most Used Weapon"), _(weapon[game.getMostUsedWeapon()].name));
162 graphics.drawString(string, 200, y += 50, true, image);
167 graphics.blit(arrows->image[0], 150, 260, image, false);
168 graphics.blit(arrows->image[2], 200, 260, image, false);
171 graphics.blit(arrows->image[1], 150, 260, image, false);
174 graphics.blit(arrows->image[3], 200, 260, image, false);
177 void loadLevelBrief(const char *levelName)
179 char briefLine[1024];
181 if (!engine.loadData(_("data/levelBrief")))
183 graphics.showErrorAndExit("Couldn't load mission briefing file (%s)", _("data/levelBrief"));
186 char *line = strtok((char*)engine.dataBuffer, "\n");
187 bool collectData = false;
188 SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
192 graphics.clearChatString();
198 sscanf(line, "%[^\n\r]", briefLine);
200 if (strcmp(briefLine, "@EOF@") == 0)
206 graphics.createChatString(line);
212 sscanf(line, "%*c %[^]]", briefLine);
213 if (strcmp(briefLine, levelName) == 0)
218 line = strtok(NULL, "\n");
229 graphics.drawChatString(image, 40);
232 void createObjectivesPanel(const char *levelName)
234 SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
236 Data *data = (Data*)gameData.dataList.getHead();
240 graphics.drawRect(1, 1, image->w - 2, image->h - 2, graphics.black, graphics.white, image);
243 char levelMIAKey[100];
248 snprintf(levelMIAKey, sizeof levelMIAKey, "%s MIAs", levelName);
250 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
252 snprintf(string, sizeof string, _("Information for %s"), _(levelName));
253 graphics.drawString(string, 200, y, true, image);
256 while (data->next != NULL)
258 data = (Data*)data->next;
260 if ((strcmp(data->key, levelName) == 0) || (strstr(data->key, levelMIAKey)))
264 if (strstr(data->key, "MIAs"))
266 // if it says 0 / 0 don't bother...
267 if (strcmp(data->value, "0 / 0"))
269 graphics.drawString(_("MIAs Rescued"), x1, y += 20, false, image);
270 snprintf(string, sizeof string, "%d / %d", data->current, data->target);
271 (data->isComplete()) ? graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00) : graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
272 graphics.drawString(string, x2, y, false, image);
275 else if (!strstr(data->value, "MIA_"))
277 if ((game.skill < 3) && (strstr(data->value, "L.R.T.S.")) && (!gameData.completedWorld))
279 graphics.drawString(_("???? ???????? ????"), x1, y += 20, false, image);
283 strlcpy(string, _(data->value), sizeof string);
285 if (strlen(string) >= 25)
288 // don't break unicode characters
289 while (((string[cut_char] >> 6) & 3) == 2)
294 string[cut_char++] = '.';
295 string[cut_char++] = '.';
296 string[cut_char++] = '.';
297 string[cut_char] = '\0';
300 graphics.drawString(string, x1, y += 20, false, image);
303 if (data->target == 1)
305 snprintf(string, sizeof string, "%s", (data->isComplete()) ? _("Completed") : _("Incomplete"));
309 snprintf(string, sizeof string, "%d / %d", data->current, data->target);
312 (data->isComplete()) ? graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00) : graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
313 graphics.drawString(string, x2, y, false, image);
317 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
321 loadLevelBrief(levelName);
324 void createMIAPanel(int start, int max)
336 SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
338 Data *data = (Data*)gameData.dataList.getHead();
340 graphics.drawRect(1, 1, image->w - 2, image->h - 2, graphics.black, graphics.white, image);
342 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
344 graphics.drawString(_("MIA Statistics"), 200, y, true, image);
346 graphics.drawString(_("Name"), x1, y += 20, false, image);
347 graphics.drawString(_("Location"), x2, y, false, image);
348 graphics.drawString(_("Status"), x3, y, false, image);
352 while (data->next != NULL)
354 data = (Data*)data->next;
356 if (strstr(data->value, "MIA_"))
364 snprintf(name, sizeof name, "%s", data->value);
367 snprintf(string, sizeof string, "%s", strtok(NULL, "_"));
368 graphics.drawString(string, x1, y += 20, false, image);
370 graphics.drawString(_(data->key), x2, y, false, image);
372 if (data->isComplete())
374 snprintf(string, sizeof string, "%s", _("Found"));
375 graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
379 snprintf(string, sizeof string, "%s", _("Missing"));
380 graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
383 graphics.drawString(string, x3, y, false, image);
385 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
394 Sprite *arrows = graphics.getSprite("HubArrows", true);
397 graphics.blit(arrows->image[0], 150, 260, image, false);
399 graphics.blit(arrows->image[1], 150, 260, image, false);
401 if ((end == 9) && (current + 9 < max))
402 graphics.blit(arrows->image[2], 200, 260, image, false);
404 graphics.blit(arrows->image[3], 200, 260, image, false);
407 bool requirementMet(const char *requiredLevel)
409 if (strstr(requiredLevel, "Stages"))
412 sscanf(requiredLevel, "%*s %d", &stages);
414 if (game.stagesCleared >= stages)
416 presentPlayerMedal(requiredLevel);
421 if (engine.cheatLevels)
426 if (strcmp(requiredLevel, "@none@") == 0)
431 return gameData.requiredLevelCleared(requiredLevel);
436 SDL_FillRect(graphics.screen, NULL, graphics.black);
437 graphics.delay(1000);
442 graphics.loadBackground("gfx/main/worldMap.jpg");
443 audio.loadMusic("music/hub");
445 // we might want this now, for medals
446 audio.loadSound(SND_ITEM, "sound/item");
448 graphics.quickSprite("cheatHeader", graphics.loadImage("gfx/main/cheats.png"));
449 graphics.quickSprite("optionsHeader", graphics.loadImage("gfx/main/options.png"));
450 graphics.quickSprite("keyHeader", graphics.loadImage("gfx/main/keyConfig.png"));
451 graphics.quickSprite("joystickHeader", graphics.loadImage("gfx/main/joystickConfig.png"));
452 graphics.quickSprite("optionsBackground", graphics.loadImage("gfx/main/optionsBackground.png"));
456 Sprite *cursor = graphics.addSprite("Cursor");
457 for (int i = 0 ; i < 6 ; i++)
459 snprintf(string, sizeof string, "gfx/main/cursor%d.png", i + 1);
460 cursor->setFrame(i, graphics.loadImage(string), 10);
463 Sprite *newTarget = graphics.addSprite("NewTarget");
464 Sprite *visitedTarget = graphics.addSprite("VisitedTarget");
466 for (int i = 0 ; i < 5 ; i++)
468 snprintf(string, sizeof string, "gfx/sprites/miaSignal%d.png", i + 1);
470 newTarget->setFrame(i, graphics.loadImage(string, -60, 0, 0), 15);
471 visitedTarget->setFrame(i, graphics.loadImage(string, 0, 0, 0), 15);
474 Sprite *hubIcons = graphics.addSprite("HubIcons");
475 for (int i = 0 ; i < 6 ; i++)
477 snprintf(string, sizeof string, "gfx/main/hubIcon%d.png", i + 1);
478 hubIcons->setFrame(i, graphics.loadImage(string), 60);
481 SDL_Surface *infoPanel = graphics.quickSprite("infoPanel", graphics.createSurface(400, 300));
483 Sprite *hubArrows = graphics.addSprite("HubArrows");
484 hubArrows->setFrame(0, graphics.loadImage("gfx/main/hubArrowLeft.png"), 60);
485 hubArrows->setFrame(1, graphics.loadImage("gfx/main/hubArrowLeft2.png"), 60);
486 hubArrows->setFrame(2, graphics.loadImage("gfx/main/hubArrowRight.png"), 60);
487 hubArrows->setFrame(3, graphics.loadImage("gfx/main/hubArrowRight2.png"), 60);
492 engine.loadData("data/hub");
494 char *line = strtok((char*)engine.dataBuffer, "\n");
496 char name[50], level[50], requiredLevel[50];
503 graphics.setFontSize(0);
504 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
506 int numberOfHubs = 0;
508 gameData.calculateWorldCompleted();
512 sscanf(line, "%*c %[^\"] %*c %*c %[^\"] %*c %d %d %*c %[^\"] %*c", name, level, &x, &y, requiredLevel);
514 if (strcmp(name, "@EOF@") == 0)
519 // don't show boss levels on Easy (they might be cheating!)
522 if (strstr(name, "BioMech"))
524 line = strtok(NULL, "\n");
529 if (requirementMet(requiredLevel))
531 if (!gameData.levelPrefectlyCleared(name))
533 hubPoint = new HubLevel;
534 hubPoint->set(name, level, x, y);
535 hubPoint->levelNameImage = graphics.getString(_(name), false);
537 (!gameData.stagePreviouslyCleared(name)) ? hubPoint->target = newTarget : hubPoint->target = visitedTarget;
539 hubList.add(hubPoint);
544 line = strtok(NULL, "\n");
549 strlcpy(level, "@none@", sizeof level);
550 strlcpy(game.stageName, "@none@", sizeof game.stageName);
552 bool showData = false;
553 bool showStats = false;
554 bool showMIAs = false;
562 Data *data = (Data*)gameData.dataList.getHead();
564 while (data->next != NULL)
566 data = (Data*)data->next;
568 if (strstr(data->value, "MIA_"))
574 bool validStage = false;
576 if ((numberOfHubs == 0) && (gameData.completedWorld))
578 game.setMapName("data/spaceStation");
579 strlcpy(game.stageName, "Space Station", sizeof game.stageName);
580 createObjectivesPanel("Space Station");
582 showStats = showMIAs = false;
585 // Wait wait wait... we're in easy mode. Game ends here.
589 return SECTION_EASYOVER;
592 presentPlayerMedal("World_Complete");
598 Uint32 frameLimit = SDL_GetTicks() + 16;
599 Uint32 now = SDL_GetTicks();
606 graphics.updateScreen();
607 graphics.drawBackground();
608 graphics.animateSprites();
612 static Graphics::SurfaceCache cache;
613 graphics.drawRect(10, 400, 620, 20, graphics.black, graphics.white, graphics.screen);
614 snprintf(string, sizeof string, "%s : %s", _("Selected Destination"), _(game.stageName));
615 graphics.drawString(string, 320, 409, true, graphics.screen, cache);
618 graphics.drawRect(10, 430, 620, 40, graphics.black, graphics.white, graphics.screen);
621 static Graphics::SurfaceCache posCache;
622 snprintf(pos, sizeof pos, "%.3d:%.3d", engine.getMouseX(), engine.getMouseY());
623 graphics.drawString(pos, 320, 15, true, graphics.screen, posCache);
629 if (config.isControl(CONTROL::RIGHT))
634 if (config.isControl(CONTROL::LEFT))
639 if (config.isControl(CONTROL::DOWN))
644 if (config.isControl(CONTROL::UP) || config.isControl(CONTROL::JUMP))
649 if ((mouseXDelta != 0) || (mouseYDelta != 0))
651 engine.setMouse(engine.getMouseX() + (int)mouseXDelta, engine.getMouseY() + (int)mouseYDelta);
656 hubPoint = (HubLevel*)hubList.getHead();
658 // Collisions for Hub Points
659 while (hubPoint->next != NULL)
661 hubPoint = (HubLevel*)hubPoint->next;
663 graphics.blit(hubPoint->target->getCurrentFrame(), hubPoint->x, hubPoint->y, graphics.screen, false);
665 if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, hubPoint->x, hubPoint->y, 16, 16))
667 labelX = engine.getMouseX();
668 labelY = engine.getMouseY() - 20;
670 labelWidth = hubPoint->levelNameImage->w / 2;
672 Math::limitInt(&labelX, 10 + labelWidth, 630 - labelWidth);
674 graphics.blit(hubPoint->levelNameImage, labelX, labelY, graphics.screen, true);
676 if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
678 game.setMapName(hubPoint->filename);
679 game.setStageName(hubPoint->stageName);
681 engine.mouseLeft = 0;
682 config.resetControl(CONTROL::FIRE);
685 if (engine.mouseRight || config.isControl(CONTROL::MAP))
687 game.setMapName(hubPoint->filename);
688 game.setStageName(hubPoint->stageName);
689 createObjectivesPanel(game.stageName);
692 engine.mouseRight = 0;
693 config.resetControl(CONTROL::MAP);
698 // Collisions for Panel
699 for (int i = ((1 - validStage) * 2) ; i < 6 ; i++)
701 graphics.blit(hubIcons->image[i], 50 + (i * 100), 440, graphics.screen, false);
702 if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, 50 + (i * 100), 440, hubIcons->image[i]->w, hubIcons->image[i]->h))
704 if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
712 createObjectivesPanel(game.stageName);
713 showData = !showData;
714 showStats = showMIAs = false;
717 createMIAPanel(miaStart, miaMax);
718 showStats = showData = false;
719 showMIAs = !showMIAs;
722 createStatsPanel(page);
723 showStats = !showStats;
724 showData = showMIAs = false;
728 graphics.setFontSize(0);
729 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
736 engine.mouseLeft = false;
737 config.resetControl(CONTROL::FIRE);
742 // Collisions for Panel Buttons
743 if ((showMIAs) || (showStats))
745 // SDL_SCANCODE_LCTRL is the "fire" button.
746 if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
748 if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, 270, 310, 32, 32))
754 Math::limitInt(&(miaStart -= 9), 0, miaMax);
755 createMIAPanel(miaStart, miaMax);
761 Math::limitInt(&(--page), 0, 2);
762 createStatsPanel(page);
765 engine.mouseLeft = 0;
766 config.resetControl(CONTROL::FIRE);
770 if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, 320, 310, 32, 32))
774 if (miaStart + 9 < miaMax)
776 Math::limitInt(&(miaStart += 9), 0, miaMax);
777 createMIAPanel(miaStart, miaMax);
783 Math::limitInt(&(++page), 0, 2);
784 createStatsPanel(page);
787 engine.mouseLeft = 0;
788 config.resetControl(CONTROL::FIRE);
793 if ((showData) || (showStats) || (showMIAs))
795 graphics.blit(infoPanel, 320, 200, graphics.screen, true);
796 if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
798 showData = showStats = showMIAs = false;
802 graphics.blit(cursor->getCurrentFrame(), engine.getMouseX(), engine.getMouseY(), graphics.screen, true);
804 doMusicInfo(SDL_GetTicks() - (now + 60000));
805 engine.delay(frameLimit);
806 frameLimit = SDL_GetTicks() + 16;