2 Copyright (C) 2004 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 void createStatsPanel(int page)
25 SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
27 graphics.drawRect(1, 1, image->w - 2, image->h - 2, graphics.black, graphics.white, image);
35 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
37 graphics.drawString(_("Metal Blob Solid : Statistics"), 200, y, true, image);
40 Sprite *arrows = graphics.getSprite("HubArrows", true);
45 graphics.drawString(_("Skill Level:"), x1, y += 20, false, image);
46 snprintf(string, sizeof string, "%s", _(skill[game.skill]));
47 graphics.drawString(string, x2, y, false, image);
49 graphics.drawString(_("Score:"), x1, y += 20, false, image);
50 snprintf(string, sizeof string, "%d", game.score);
51 graphics.drawString(string, x2, y, false, image);
53 graphics.drawString(_("MIAs Saved:"), x1, y += 20, false, image);
54 snprintf(string, sizeof string, "%d", game.totalMIAsRescued);
55 graphics.drawString(string, x2, y, false, image);
57 graphics.drawString(_("Objectives Completed:"), x1, y += 20, false, image);
58 snprintf(string, sizeof string, "%d", game.totalObjectivesCompleted);
59 graphics.drawString(string, x2, y, false, image);
61 // Don't do this on Extreme or it will always say 100%
64 graphics.drawString(_("Percentage Complete:"), x1, y += 20, false, image);
65 snprintf(string, sizeof string, "%d%%", gameData.getPercentageComplete());
66 graphics.drawString(string, x2, y, false, image);
69 snprintf(string, sizeof string, "%s - %.2d:%.2d:%.2d", _("Total Game Time"), game.totalHours, game.totalMinutes, game.totalSeconds);
70 graphics.drawString(string, 200, y += 110, true, image);
76 graphics.drawString(_("Enemies Defeated:"), x1, y += 20, false, image);
77 snprintf(string, sizeof string, "%d", game.totalEnemiesDefeated);
78 graphics.drawString(string, x2, y, false, image);
80 graphics.drawString(_("Items Collected:"), x1, y += 20, false, image);
81 snprintf(string, sizeof string, "%d", game.totalItemsCollected);
82 graphics.drawString(string, x2, y, false, image);
84 graphics.drawString(_("Bonuses Picked Up:"), x1, y += 20, false, image);
85 snprintf(string, sizeof string, "%d", game.totalBonusesCollected);
86 graphics.drawString(string, x2, y, false, image);
88 graphics.drawString(_("Best Combo:"), x1, y += 20, false, image);
89 snprintf(string, sizeof string, _("%d Hits"), game.maxComboHits);
90 graphics.drawString(string, x2, y, false, image);
92 graphics.drawString(_("Missions Started:"), x1, y += 20, false, image);
93 snprintf(string, sizeof string, "%d", game.levelsStarted);
94 graphics.drawString(string, x2, y, false, image);
96 graphics.drawString(_("Continues Used:"), x1, y += 20, false, image);
97 snprintf(string, sizeof string, "%d", game.continuesUsed);
98 graphics.drawString(string, x2, y, false, image);
100 if ((game.continuesUsed > 0) && (game.levelsStarted > 0))
102 graphics.drawString(_("Average Continue Usage:"), x1, y += 20, false, image);
103 snprintf(string, sizeof string, "%d", (game.continuesUsed / game.levelsStarted));
104 graphics.drawString(string, x2, y, false, image);
107 graphics.drawString(_("Escapes Used:"), x1, y += 20, false, image);
108 snprintf(string, sizeof string, "%d", game.escapes);
109 graphics.drawString(string, x2, y, false, image);
119 graphics.drawString(_("Weapon"), x1, y += 20, false, image);
120 graphics.drawString(_("Ammo Used"), x2, y, false, image);
121 graphics.drawString(_("Accuracy"), x3, y, false, image);
123 graphics.drawString(_("Pistol"), x1, y += 30, false, image);
124 snprintf(string, sizeof string, "%d", game.bulletsFired[WP_PISTOL]);
125 graphics.drawString(string, x2, y, false, image);
126 snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_PISTOL));
127 graphics.drawString(string, x3, y, false, image);
129 graphics.drawString(_("Machine Gun"), x1, y += 20, false, image);
130 snprintf(string, sizeof string, "%d", game.bulletsFired[WP_MACHINEGUN]);
131 graphics.drawString(string, x2, y, false, image);
132 snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_MACHINEGUN));
133 graphics.drawString(string, x3, y, false, image);
135 graphics.drawString(_("Laser Cannon"), x1, y += 20, false, image);
136 snprintf(string, sizeof string, "%d", game.bulletsFired[WP_LASER]);
137 graphics.drawString(string, x2, y, false, image);
138 snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_LASER));
139 graphics.drawString(string, x3, y, false, image);
141 graphics.drawString(_("Grenades"), x1, y += 20, false, image);
142 snprintf(string, sizeof string, "%d", game.bulletsFired[WP_GRENADES]);
143 graphics.drawString(string, x2, y, false, image);
144 snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_GRENADES));
145 graphics.drawString(string, x3, y, false, image);
147 graphics.drawString(_("Spread Gun"), x1, y += 20, false, image);
148 snprintf(string, sizeof string, "%d", game.bulletsFired[WP_SPREAD]);
149 graphics.drawString(string, x2, y, false, image);
150 snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_SPREAD));
151 graphics.drawString(string, x3, y, false, image);
153 graphics.drawString(_("Total"), x1, y += 30, false, image);
154 snprintf(string, sizeof string, "%d", game.getTotalBulletsFired());
155 graphics.drawString(string, x2, y, false, image);
156 snprintf(string, sizeof string, "%d%%", game.getTotalAccuracy());
157 graphics.drawString(string, x3, y, false, image);
159 snprintf(string, sizeof string, "%s - %s", _("Most Used Weapon"), _(weapon[game.getMostUsedWeapon()].name));
160 graphics.drawString(string, 200, y += 50, true, image);
165 graphics.blit(arrows->image[0], 150, 260, image, false);
166 graphics.blit(arrows->image[2], 200, 260, image, false);
169 graphics.blit(arrows->image[1], 150, 260, image, false);
172 graphics.blit(arrows->image[3], 200, 260, image, false);
175 void loadLevelBrief(const char *levelName)
177 char briefLine[1024];
179 if (!engine.loadData(_("data/levelBrief")))
181 graphics.showErrorAndExit("Couldn't load mission briefing file (%s)", _("data/levelBrief"));
184 char *line = strtok((char*)engine.dataBuffer, "\n");
185 bool collectData = false;
186 SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
190 graphics.clearChatString();
196 sscanf(line, "%[^\n\r]", briefLine);
198 if (strcmp(briefLine, "@EOF@") == 0)
204 graphics.createChatString(line);
210 sscanf(line, "%*c %[^]]", briefLine);
211 if (strcmp(briefLine, levelName) == 0)
216 line = strtok(NULL, "\n");
227 graphics.drawChatString(image, 40);
230 void createObjectivesPanel(const char *levelName)
232 SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
234 Data *data = (Data*)gameData.dataList.getHead();
238 graphics.drawRect(1, 1, image->w - 2, image->h - 2, graphics.black, graphics.white, image);
241 char levelMIAKey[100];
246 snprintf(levelMIAKey, sizeof levelMIAKey, "%s MIAs", levelName);
248 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
250 snprintf(string, sizeof string, _("Information for %s"), _(levelName));
251 graphics.drawString(string, 200, y, true, image);
254 while (data->next != NULL)
256 data = (Data*)data->next;
258 if ((strcmp(data->key, levelName) == 0) || (strstr(data->key, levelMIAKey)))
262 if (strstr(data->key, "MIAs"))
264 // if it says 0 / 0 don't bother...
265 if (strcmp(data->value, "0 / 0"))
267 graphics.drawString(_("MIAs Rescued"), x1, y += 20, false, image);
268 snprintf(string, sizeof string, "%d / %d", data->current, data->target);
269 (data->isComplete()) ? graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00) : graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
270 graphics.drawString(string, x2, y, false, image);
273 else if (!strstr(data->value, "MIA_"))
275 if ((game.skill < 3) && (strstr(data->value, "L.R.T.S.")) && (!gameData.completedWorld))
277 graphics.drawString(_("???? ???????? ????"), x1, y += 20, false, image);
281 strncpy(string, _(data->value), sizeof string);
283 if (strlen(string) >= 25)
286 // don't break unicode characters
287 while (((string[cut_char] >> 6) & 3) == 2)
292 string[cut_char++] = '.';
293 string[cut_char++] = '.';
294 string[cut_char++] = '.';
295 string[cut_char] = '\0';
298 graphics.drawString(string, x1, y += 20, false, image);
301 if (data->target == 1)
303 snprintf(string, sizeof string, "%s", (data->isComplete()) ? _("Completed") : _("Incomplete"));
307 snprintf(string, sizeof string, "%d / %d", data->current, data->target);
310 (data->isComplete()) ? graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00) : graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
311 graphics.drawString(string, x2, y, false, image);
315 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
319 loadLevelBrief(levelName);
322 void createMIAPanel(int start, int max)
334 SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
336 Data *data = (Data*)gameData.dataList.getHead();
338 graphics.drawRect(1, 1, image->w - 2, image->h - 2, graphics.black, graphics.white, image);
340 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
342 graphics.drawString(_("MIA Statistics"), 200, y, true, image);
344 graphics.drawString(_("Name"), x1, y += 20, false, image);
345 graphics.drawString(_("Location"), x2, y, false, image);
346 graphics.drawString(_("Status"), x3, y, false, image);
350 while (data->next != NULL)
352 data = (Data*)data->next;
354 if (strstr(data->value, "MIA_"))
362 snprintf(name, sizeof name, "%s", data->value);
365 snprintf(string, sizeof string, "%s", strtok(NULL, "_"));
366 graphics.drawString(string, x1, y += 20, false, image);
368 graphics.drawString(_(data->key), x2, y, false, image);
370 if (data->isComplete())
372 snprintf(string, sizeof string, "%s", _("Found"));
373 graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
377 snprintf(string, sizeof string, "%s", _("Missing"));
378 graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
381 graphics.drawString(string, x3, y, false, image);
383 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
392 Sprite *arrows = graphics.getSprite("HubArrows", true);
395 graphics.blit(arrows->image[0], 150, 260, image, false);
397 graphics.blit(arrows->image[1], 150, 260, image, false);
399 if ((end == 9) && (current + 9 < max))
400 graphics.blit(arrows->image[2], 200, 260, image, false);
402 graphics.blit(arrows->image[3], 200, 260, image, false);
405 bool requirementMet(const char *requiredLevel)
407 if (strstr(requiredLevel, "Stages"))
410 sscanf(requiredLevel, "%*s %d", &stages);
412 if (game.stagesCleared >= stages)
414 presentPlayerMedal(requiredLevel);
419 if (engine.cheatLevels)
424 if (strcmp(requiredLevel, "@none@") == 0)
429 return gameData.requiredLevelCleared(requiredLevel);
434 SDL_FillRect(graphics.screen, NULL, graphics.black);
435 graphics.delay(1000);
440 graphics.loadBackground("gfx/main/worldMap.jpg");
441 audio.loadMusic("music/hub");
443 // we might want this now, for medals
444 audio.loadSound(SND_ITEM, "sound/item.wav");
446 graphics.quickSprite("cheatHeader", graphics.loadImage("gfx/main/cheats.png"));
447 graphics.quickSprite("optionsHeader", graphics.loadImage("gfx/main/options.png"));
448 graphics.quickSprite("keyHeader", graphics.loadImage("gfx/main/keyConfig.png"));
449 graphics.quickSprite("joystickHeader", graphics.loadImage("gfx/main/joystickConfig.png"));
450 graphics.quickSprite("optionsBackground", graphics.loadImage("gfx/main/optionsBackground.png"));
454 Sprite *cursor = graphics.addSprite("Cursor");
455 for (int i = 0 ; i < 6 ; i++)
457 snprintf(string, sizeof string, "gfx/main/cursor%d.png", i + 1);
458 cursor->setFrame(i, graphics.loadImage(string), 10);
461 Sprite *newTarget = graphics.addSprite("NewTarget");
462 Sprite *visitedTarget = graphics.addSprite("VisitedTarget");
464 for (int i = 0 ; i < 5 ; i++)
466 snprintf(string, sizeof string, "gfx/sprites/miaSignal%d.png", i + 1);
468 newTarget->setFrame(i, graphics.loadImage(string, -60, 0, 0), 15);
469 visitedTarget->setFrame(i, graphics.loadImage(string, 0, 0, 0), 15);
472 Sprite *hubIcons = graphics.addSprite("HubIcons");
473 for (int i = 0 ; i < 6 ; i++)
475 snprintf(string, sizeof string, "gfx/main/hubIcon%d.png", i + 1);
476 hubIcons->setFrame(i, graphics.loadImage(string), 60);
479 SDL_Surface *infoPanel = graphics.quickSprite("infoPanel", graphics.createSurface(400, 300));
481 Sprite *hubArrows = graphics.addSprite("HubArrows");
482 hubArrows->setFrame(0, graphics.loadImage("gfx/main/hubArrowLeft.png"), 60);
483 hubArrows->setFrame(1, graphics.loadImage("gfx/main/hubArrowLeft2.png"), 60);
484 hubArrows->setFrame(2, graphics.loadImage("gfx/main/hubArrowRight.png"), 60);
485 hubArrows->setFrame(3, graphics.loadImage("gfx/main/hubArrowRight2.png"), 60);
490 engine.loadData("data/hub");
492 char *line = strtok((char*)engine.dataBuffer, "\n");
494 char name[50], level[50], requiredLevel[50];
501 graphics.setFontSize(0);
502 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
504 int numberOfHubs = 0;
506 gameData.calculateWorldCompleted();
510 sscanf(line, "%*c %[^\"] %*c %*c %[^\"] %*c %d %d %*c %[^\"] %*c", name, level, &x, &y, requiredLevel);
512 if (strcmp(name, "@EOF@") == 0)
517 // don't show boss levels on Easy (they might be cheating!)
520 if (strstr(name, "BioMech"))
522 line = strtok(NULL, "\n");
527 if (requirementMet(requiredLevel))
529 if (!gameData.levelPrefectlyCleared(name))
531 hubPoint = new HubLevel;
532 hubPoint->set(name, level, x, y);
533 hubPoint->levelNameImage = graphics.getString(_(name), false);
535 (!gameData.stagePreviouslyCleared(name)) ? hubPoint->target = newTarget : hubPoint->target = visitedTarget;
537 hubList.add(hubPoint);
542 line = strtok(NULL, "\n");
547 strncpy(level, "@none@", sizeof level);
548 strncpy(game.stageName, "@none@", sizeof game.stageName);
550 bool showData = false;
551 bool showStats = false;
552 bool showMIAs = false;
560 Data *data = (Data*)gameData.dataList.getHead();
562 while (data->next != NULL)
564 data = (Data*)data->next;
566 if (strstr(data->value, "MIA_"))
572 bool validStage = false;
574 if ((numberOfHubs == 0) && (gameData.completedWorld))
576 game.setMapName("data/spaceStation");
577 strncpy(game.stageName, "Space Station", sizeof game.stageName);
578 createObjectivesPanel("Space Station");
580 showStats = showMIAs = false;
583 // Wait wait wait... we're in easy mode. Game ends here.
587 return SECTION_EASYOVER;
590 presentPlayerMedal("World_Complete");
596 Uint32 frameLimit = SDL_GetTicks() + 16;
603 graphics.updateScreen();
604 graphics.drawBackground();
605 graphics.animateSprites();
609 graphics.drawRect(10, 400, 620, 20, graphics.black, graphics.white, graphics.screen);
610 snprintf(string, sizeof string, "%s : %s", _("Selected Destination"), _(game.stageName));
611 graphics.drawString(string, 320, 409, true, graphics.screen);
614 graphics.drawRect(10, 430, 620, 40, graphics.black, graphics.white, graphics.screen);
617 snprintf(pos, sizeof pos, "%.3d:%.3d", engine.getMouseX(), engine.getMouseY());
618 graphics.drawString(pos, 320, 15, true, graphics.screen);
624 if (config.isControl(CONTROL::RIGHT))
629 if (config.isControl(CONTROL::LEFT))
634 if (config.isControl(CONTROL::DOWN))
639 if (config.isControl(CONTROL::UP) || config.isControl(CONTROL::JUMP))
644 if ((mouseXDelta != 0) || (mouseYDelta != 0))
646 engine.setMouse(engine.getMouseX() + (int)mouseXDelta, engine.getMouseY() + (int)mouseYDelta);
651 hubPoint = (HubLevel*)hubList.getHead();
653 // Collisions for Hub Points
654 while (hubPoint->next != NULL)
656 hubPoint = (HubLevel*)hubPoint->next;
658 graphics.blit(hubPoint->target->getCurrentFrame(), hubPoint->x, hubPoint->y, graphics.screen, false);
660 if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, hubPoint->x, hubPoint->y, 16, 16))
662 labelX = engine.getMouseX();
663 labelY = engine.getMouseY() - 20;
665 labelWidth = hubPoint->levelNameImage->w / 2;
667 Math::limitInt(&labelX, 10 + labelWidth, 630 - labelWidth);
669 graphics.blit(hubPoint->levelNameImage, labelX, labelY, graphics.screen, true);
671 if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
673 game.setMapName(hubPoint->filename);
674 game.setStageName(hubPoint->stageName);
676 engine.mouseLeft = 0;
677 config.resetControl(CONTROL::FIRE);
680 if (engine.mouseRight || config.isControl(CONTROL::MAP))
682 game.setMapName(hubPoint->filename);
683 game.setStageName(hubPoint->stageName);
684 createObjectivesPanel(game.stageName);
687 engine.mouseRight = 0;
688 config.resetControl(CONTROL::MAP);
693 // Collisions for Panel
694 for (int i = ((1 - validStage) * 2) ; i < 6 ; i++)
696 graphics.blit(hubIcons->image[i], 50 + (i * 100), 440, graphics.screen, false);
697 if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, 50 + (i * 100), 440, hubIcons->image[i]->w, hubIcons->image[i]->h))
699 if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
707 createObjectivesPanel(game.stageName);
708 showData = !showData;
709 showStats = showMIAs = false;
712 createMIAPanel(miaStart, miaMax);
713 showStats = showData = false;
714 showMIAs = !showMIAs;
717 createStatsPanel(page);
718 showStats = !showStats;
719 showData = showMIAs = false;
723 graphics.setFontSize(0);
724 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
731 engine.mouseLeft = false;
732 config.resetControl(CONTROL::FIRE);
737 // Collisions for Panel Buttons
738 if ((showMIAs) || (showStats))
740 // SDLK_LCTRL is the "fire" button.
741 if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
743 if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, 270, 310, 32, 32))
749 Math::limitInt(&(miaStart -= 9), 0, miaMax);
750 createMIAPanel(miaStart, miaMax);
756 Math::limitInt(&(--page), 0, 2);
757 createStatsPanel(page);
760 engine.mouseLeft = 0;
761 config.resetControl(CONTROL::FIRE);
765 if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, 320, 310, 32, 32))
769 if (miaStart + 9 < miaMax)
771 Math::limitInt(&(miaStart += 9), 0, miaMax);
772 createMIAPanel(miaStart, miaMax);
778 Math::limitInt(&(++page), 0, 2);
779 createStatsPanel(page);
782 engine.mouseLeft = 0;
783 config.resetControl(CONTROL::FIRE);
788 if ((showData) || (showStats) || (showMIAs))
790 graphics.blit(infoPanel, 320, 200, graphics.screen, true);
791 if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
793 showData = showStats = showMIAs = false;
797 graphics.blit(cursor->getCurrentFrame(), engine.getMouseX(), engine.getMouseY(), graphics.screen, true);
799 engine.delay(frameLimit);
800 frameLimit = SDL_GetTicks() + 16;