]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/hub.cpp
Fix reading one element past the end of an array.
[quix0rs-blobwars.git] / src / hub.cpp
1 /*
2 Copyright (C) 2004-2011 Parallel Realities
3 Copyright (C) 2011-2015 Perpendicular Dimensions
4
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.
9
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.
13
14 See the GNU General Public License for more details.
15
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.
19
20 */
21
22 #include "hub.h"
23
24 extern void doMusicInfo(unsigned int);
25
26 void createStatsPanel(int page)
27 {
28         SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
29
30         graphics.drawRect(1, 1, image->w - 2, image->h - 2, graphics.black, graphics.white, image);
31
32         char string[100];
33         int x1 = 80;
34         int x2 = 270;
35         int x3 = 300;
36         int y = 15;
37
38         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
39
40         graphics.drawString(_("Metal Blob Solid : Statistics"), 200, y, true, image);
41         y += 10;
42         
43         Sprite *arrows = graphics.getSprite("HubArrows", true);
44
45         switch (page)
46         {
47                 case 0:
48                         graphics.drawString(_("Skill Level:"), x1, y += 20, false, image);
49                         snprintf(string, sizeof string, "%s", _(skill[game.skill]));
50                         graphics.drawString(string, x2, y, false, image);
51
52                         graphics.drawString(_("Score:"), x1, y += 20, false, image);
53                         snprintf(string, sizeof string, "%d", game.score);
54                         graphics.drawString(string, x2, y, false, image);
55
56                         graphics.drawString(_("MIAs Saved:"), x1, y += 20, false, image);
57                         snprintf(string, sizeof string, "%d", game.totalMIAsRescued);
58                         graphics.drawString(string, x2, y, false, image);
59
60                         graphics.drawString(_("Objectives Completed:"), x1, y += 20, false, image);
61                         snprintf(string, sizeof string, "%d", game.totalObjectivesCompleted);
62                         graphics.drawString(string, x2, y, false, image);
63
64                         // Don't do this on Extreme or it will always say 100%
65                         if (game.skill < 3)
66                         {
67                                 graphics.drawString(_("Percentage Complete:"), x1, y += 20, false, image);
68                                 snprintf(string, sizeof string, "%d%%", gameData.getPercentageComplete());
69                                 graphics.drawString(string, x2, y, false, image);
70                         }
71
72                         snprintf(string, sizeof string, "%s - %.2d:%.2d:%.2d", _("Total Game Time"), game.totalHours, game.totalMinutes, game.totalSeconds);
73                         graphics.drawString(string, 200, y += 110, true, image);
74
75                         break;
76
77                 case 1:
78
79                         graphics.drawString(_("Enemies Defeated:"), x1, y += 20, false, image);
80                         snprintf(string, sizeof string, "%d", game.totalEnemiesDefeated);
81                         graphics.drawString(string, x2, y, false, image);
82
83                         graphics.drawString(_("Items Collected:"), x1, y += 20, false, image);
84                         snprintf(string, sizeof string, "%d", game.totalItemsCollected);
85                         graphics.drawString(string, x2, y, false, image);
86
87                         graphics.drawString(_("Bonuses Picked Up:"), x1, y += 20, false, image);
88                         snprintf(string, sizeof string, "%d", game.totalBonusesCollected);
89                         graphics.drawString(string, x2, y, false, image);
90
91                         graphics.drawString(_("Best Combo:"), x1, y += 20, false, image);
92                         snprintf(string, sizeof string, _("%d Hits"), game.maxComboHits);
93                         graphics.drawString(string, x2, y, false, image);
94                         
95                         graphics.drawString(_("Missions Started:"), x1, y += 20, false, image);
96                         snprintf(string, sizeof string, "%d", game.levelsStarted);
97                         graphics.drawString(string, x2, y, false, image);
98
99                         graphics.drawString(_("Continues Used:"), x1, y += 20, false, image);
100                         snprintf(string, sizeof string, "%d", game.continuesUsed);
101                         graphics.drawString(string, x2, y, false, image);
102                         
103                         if ((game.continuesUsed > 0) && (game.levelsStarted > 0))
104                         {
105                                 graphics.drawString(_("Average Continue Usage:"), x1, y += 20, false, image);
106                                 snprintf(string, sizeof string, "%d", (game.continuesUsed / game.levelsStarted));
107                                 graphics.drawString(string, x2, y, false, image);
108                         }
109
110                         graphics.drawString(_("Escapes Used:"), x1, y += 20, false, image);
111                         snprintf(string, sizeof string, "%d", game.escapes);
112                         graphics.drawString(string, x2, y, false, image);
113
114                         break;
115
116                 case 2:
117                 
118                         x1 = 20;
119                         x2 = 170;
120                         x3 = 300;
121
122                         graphics.drawString(_("Weapon"), x1, y += 20, false, image);
123                         graphics.drawString(_("Ammo Used"), x2, y, false, image);
124                         graphics.drawString(_("Accuracy"), x3, y, false, image);
125
126                         graphics.drawString(_("Pistol"), x1, y += 30, false, image);
127                         snprintf(string, sizeof string, "%d", game.bulletsFired[WP_PISTOL]);
128                         graphics.drawString(string, x2, y, false, image);
129                         snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_PISTOL));
130                         graphics.drawString(string, x3, y, false, image);
131
132                         graphics.drawString(_("Machine Gun"), x1, y += 20, false, image);
133                         snprintf(string, sizeof string, "%d", game.bulletsFired[WP_MACHINEGUN]);
134                         graphics.drawString(string, x2, y, false, image);
135                         snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_MACHINEGUN));
136                         graphics.drawString(string, x3, y, false, image);
137
138                         graphics.drawString(_("Laser Cannon"), x1, y += 20, false, image);
139                         snprintf(string, sizeof string, "%d", game.bulletsFired[WP_LASER]);
140                         graphics.drawString(string, x2, y, false, image);
141                         snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_LASER));
142                         graphics.drawString(string, x3, y, false, image);
143                         
144                         graphics.drawString(_("Grenades"), x1, y += 20, false, image);
145                         snprintf(string, sizeof string, "%d", game.bulletsFired[WP_GRENADES]);
146                         graphics.drawString(string, x2, y, false, image);
147                         snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_GRENADES));
148                         graphics.drawString(string, x3, y, false, image);
149
150                         graphics.drawString(_("Spread Gun"), x1, y += 20, false, image);
151                         snprintf(string, sizeof string, "%d", game.bulletsFired[WP_SPREAD]);
152                         graphics.drawString(string, x2, y, false, image);
153                         snprintf(string, sizeof string, "%d%%", game.getWeaponAccuracy(WP_SPREAD));
154                         graphics.drawString(string, x3, y, false, image);
155                         
156                         graphics.drawString(_("Total"), x1, y += 30, false, image);
157                         snprintf(string, sizeof string, "%d", game.getTotalBulletsFired());
158                         graphics.drawString(string, x2, y, false, image);
159                         snprintf(string, sizeof string, "%d%%", game.getTotalAccuracy());
160                         graphics.drawString(string, x3, y, false, image);
161
162                         snprintf(string, sizeof string, "%s - %s", _("Most Used Weapon"), _(weapon[game.getMostUsedWeapon()].name));
163                         graphics.drawString(string, 200, y += 50, true, image);
164
165                         break;
166         }
167
168         graphics.blit(arrows->image[0], 150, 260, image, false);
169         graphics.blit(arrows->image[2], 200, 260, image, false);
170
171         if (page == 0)
172                 graphics.blit(arrows->image[1], 150, 260, image, false);
173
174         if (page == 2)
175                 graphics.blit(arrows->image[3], 200, 260, image, false);
176 }
177
178 void loadLevelBrief(const char *levelName)
179 {
180         char briefLine[1024];
181
182         if (!engine.loadData(_("data/levelBrief")))
183         {
184                 graphics.showErrorAndExit("Couldn't load mission briefing file (%s)", _("data/levelBrief"));
185         }
186
187         char *line = strtok((char*)engine.dataBuffer, "\n");
188         bool collectData = false;
189         SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
190
191         int i = 0 ;
192
193         graphics.clearChatString();
194
195         while (true)
196         {
197                 if (collectData)
198                 {
199                         sscanf(line, "%[^\n\r]", briefLine);
200
201                         if (strcmp(briefLine, "@EOF@") == 0)
202                                 break;
203
204                         if (line[0] == '[')
205                                 break;
206
207                         graphics.createChatString(line);
208                 }
209                 else
210                 {
211                         if (line[0] == '[')
212                         {
213                                 sscanf(line, "%*c %[^]]", briefLine);
214                                 if (strcmp(briefLine, levelName) == 0)
215                                         collectData = true;
216                         }
217                 }
218
219                 line = strtok(NULL, "\n");
220                 if (line == NULL)
221                         break;
222
223                 i++;
224
225                 // sanity check!
226                 if (i == 10000)
227                         break;
228         }
229         
230         graphics.drawChatString(image, 40);
231 }
232
233 void createObjectivesPanel(const char *levelName)
234 {
235         SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
236
237         Data *data = (Data*)gameData.dataList.getHead();
238
239         bool found = false;
240
241         graphics.drawRect(1, 1, image->w - 2, image->h - 2, graphics.black, graphics.white, image);
242
243         char string[100];
244         char levelMIAKey[100];
245         int x1 = 60;
246         int x2 = 260;
247         int y = 15;
248         
249         snprintf(levelMIAKey, sizeof levelMIAKey, "%s MIAs", levelName);
250
251         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
252
253         snprintf(string, sizeof string, _("Information for %s"), _(levelName));
254         graphics.drawString(string, 200, y, true, image);
255         y += 10;
256
257         while (data->next != NULL)
258         {
259                 data = (Data*)data->next;
260
261                 if ((strcmp(data->key, levelName) == 0) || (strstr(data->key, levelMIAKey)))
262                 {
263                         found = true;
264
265                         if (strstr(data->key, "MIAs"))
266                         {
267                                 // if it says 0 / 0 don't bother...
268                                 if (strcmp(data->value, "0 / 0"))
269                                 {
270                                         graphics.drawString(_("MIAs Rescued"), x1, y += 20, false, image);
271                                         snprintf(string, sizeof string, "%d / %d", data->current, data->target);
272                                         (data->isComplete()) ? graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00) : graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
273                                         graphics.drawString(string, x2, y, false, image);
274                                 }
275                         }
276                         else if (!strstr(data->value, "MIA_"))
277                         {
278                                 if ((game.skill < 3) &&  (strstr(data->value, "L.R.T.S.")) && (!gameData.completedWorld))
279                                 {
280                                         graphics.drawString(_("???? ???????? ????"), x1, y += 20, false, image);
281                                 }
282                                 else
283                                 {
284                                         strlcpy(string, _(data->value), sizeof string);
285                                         
286                                         if (strlen(string) >= 25)
287                                         {
288                                                 int cut_char = 25;
289                                                 // don't break unicode characters
290                                                 while (((string[cut_char] >> 6) & 3) == 2)
291                                                 {
292                                                         cut_char--;
293                                                 }
294
295                                                 string[cut_char++] = '.';
296                                                 string[cut_char++] = '.';
297                                                 string[cut_char++] = '.';
298                                                 string[cut_char] = '\0';
299                                         }
300                                         
301                                         graphics.drawString(string, x1, y += 20, false, image);
302                                 }
303                                 
304                                 if (data->target == 1)
305                                 {
306                                         snprintf(string, sizeof string, "%s", (data->isComplete()) ? _("Completed") : _("Incomplete"));
307                                 }
308                                 else
309                                 {
310                                         snprintf(string, sizeof string, "%d / %d", data->current, data->target);
311                                 }
312                                 
313                                 (data->isComplete()) ? graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00) : graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
314                                 graphics.drawString(string, x2, y, false, image);
315                         }
316                 }
317
318                 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
319         }
320
321         if (!found)
322                 loadLevelBrief(levelName);
323 }
324
325 void createMIAPanel(int start, int max)
326 {
327         char string[100];
328         char name[100];
329         int x1 = 20;
330         int x2 = 130;
331         int x3 = 310;
332         int y = 15;
333
334         int current = 0;
335         int end = 0;
336
337         SDL_Surface *image = graphics.getSprite("infoPanel", true)->image[0];
338
339         Data *data = (Data*)gameData.dataList.getHead();
340
341         graphics.drawRect(1, 1, image->w - 2, image->h - 2, graphics.black, graphics.white, image);
342
343         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
344
345         graphics.drawString(_("MIA Statistics"), 200, y, true, image);
346
347         graphics.drawString(_("Name"), x1, y += 20, false, image);
348         graphics.drawString(_("Location"), x2, y, false, image);
349         graphics.drawString(_("Status"), x3, y, false, image);
350
351         y += 10;
352
353         while (data->next != NULL)
354         {
355                 data = (Data*)data->next;
356
357                 if (strstr(data->value, "MIA_"))
358                 {
359                         if (current < start)
360                         {
361                                 current++;
362                                 continue;
363                         }
364
365                         snprintf(name, sizeof name, "%s", data->value);
366                         strtok(name, "_");
367
368                         snprintf(string, sizeof string, "%s", strtok(NULL, "_"));
369                         graphics.drawString(string, x1, y += 20, false, image);
370
371                         graphics.drawString(_(data->key), x2, y, false, image);
372
373                         if (data->isComplete())
374                         {
375                                 snprintf(string, sizeof string, "%s", _("Found"));
376                                 graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
377                         }
378                         else
379                         {
380                                 snprintf(string, sizeof string, "%s", _("Missing"));
381                                 graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
382                         }
383
384                         graphics.drawString(string, x3, y, false, image);
385
386                         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
387
388                         end++;
389
390                         if (end == 9)
391                                 break;
392                 }
393         }
394
395         Sprite *arrows = graphics.getSprite("HubArrows", true);
396
397         if (start > 0)
398                 graphics.blit(arrows->image[0], 150, 260, image, false);
399         else
400                 graphics.blit(arrows->image[1], 150, 260, image, false);
401
402         if ((end == 9) && (current + 9 < max))
403                 graphics.blit(arrows->image[2], 200, 260, image, false);
404         else
405                 graphics.blit(arrows->image[3], 200, 260, image, false);
406 }
407
408 bool requirementMet(const char *requiredLevel)
409 {
410         if (strstr(requiredLevel, "Stages"))
411         {
412                 int stages = 0;
413                 sscanf(requiredLevel, "%*s %d", &stages);
414
415                 if (game.stagesCleared >= stages)
416                 {
417                         presentPlayerMedal(requiredLevel);
418                         return true;
419                 }
420         }
421         
422         if (engine.cheatLevels)
423         {
424                 return true;
425         }
426
427         if (strcmp(requiredLevel, "@none@") == 0)
428         {
429                 return true;
430         }
431
432         return gameData.requiredLevelCleared(requiredLevel);
433 }
434
435 int doHub()
436 {
437         SDL_FillRect(graphics.screen, NULL, graphics.black);
438         graphics.delay(1000);
439         
440         graphics.free();
441         audio.free();
442
443         graphics.loadBackground("gfx/main/worldMap.jpg");
444         audio.loadMusic("music/hub");
445         
446         // we might want this now, for medals
447         audio.loadSound(SND_ITEM, "sound/item");
448         
449         graphics.quickSprite("cheatHeader", graphics.loadImage("gfx/main/cheats.png"));
450         graphics.quickSprite("optionsHeader", graphics.loadImage("gfx/main/options.png"));
451         graphics.quickSprite("keyHeader", graphics.loadImage("gfx/main/keyConfig.png"));
452         graphics.quickSprite("joystickHeader", graphics.loadImage("gfx/main/joystickConfig.png"));
453         graphics.quickSprite("optionsBackground", graphics.loadImage("gfx/main/optionsBackground.png"));
454
455         char string[80];
456
457         Sprite *cursor = graphics.addSprite("Cursor");
458         for (int i = 0 ; i < 6 ; i++)
459         {
460                 snprintf(string, sizeof string, "gfx/main/cursor%d.png", i + 1);
461                 cursor->setFrame(i, graphics.loadImage(string), 10);
462         }
463
464         Sprite *newTarget = graphics.addSprite("NewTarget");
465         Sprite *visitedTarget = graphics.addSprite("VisitedTarget");
466         
467         for (int i = 0 ; i < 5 ; i++)
468         {
469                 snprintf(string, sizeof string, "gfx/sprites/miaSignal%d.png", i + 1);
470                 
471                 newTarget->setFrame(i, graphics.loadImage(string, -60, 0, 0), 15);
472                 visitedTarget->setFrame(i, graphics.loadImage(string, 0, 0, 0), 15);
473         }
474
475         Sprite *hubIcons = graphics.addSprite("HubIcons");
476         for (int i = 0 ; i < 6 ; i++)
477         {
478                 snprintf(string, sizeof string, "gfx/main/hubIcon%d.png", i + 1);
479                 hubIcons->setFrame(i, graphics.loadImage(string), 60);
480         }
481
482         SDL_Surface *infoPanel = graphics.quickSprite("infoPanel", graphics.createSurface(400, 300));
483
484         Sprite *hubArrows = graphics.addSprite("HubArrows");
485         hubArrows->setFrame(0, graphics.loadImage("gfx/main/hubArrowLeft.png"), 60);
486         hubArrows->setFrame(1, graphics.loadImage("gfx/main/hubArrowLeft2.png"), 60);
487         hubArrows->setFrame(2, graphics.loadImage("gfx/main/hubArrowRight.png"), 60);
488         hubArrows->setFrame(3, graphics.loadImage("gfx/main/hubArrowRight2.png"), 60);
489
490         List hubList;
491         HubLevel *hubPoint;
492
493         engine.loadData("data/hub");
494
495         char *line = strtok((char*)engine.dataBuffer, "\n");
496
497         char name[50], level[50], requiredLevel[50];
498         int x, y;
499
500         #if DEBUG
501         char pos[50];
502         #endif
503
504         graphics.setFontSize(0);
505         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
506         
507         int numberOfHubs = 0;
508         
509         gameData.calculateWorldCompleted();
510
511         while (true)
512         {
513                 sscanf(line, "%*c %[^\"] %*c %*c %[^\"] %*c %d %d %*c %[^\"] %*c", name, level, &x, &y, requiredLevel);
514
515                 if (strcmp(name, "@EOF@") == 0)
516                 {
517                         break;
518                 }
519                 
520                 // don't show boss levels on Easy (they might be cheating!)
521                 if (game.skill == 0)
522                 {
523                         if (strstr(name, "BioMech"))
524                         {
525                                 line = strtok(NULL, "\n");
526                                 continue;
527                         }
528                 }
529
530                 if (requirementMet(requiredLevel))
531                 {
532                         if (!gameData.levelPrefectlyCleared(name))
533                         {
534                                 hubPoint = new HubLevel;
535                                 hubPoint->set(name, level, x, y);
536                                 hubPoint->levelNameImage = graphics.getString(_(name), false);
537                                 
538                                 (!gameData.stagePreviouslyCleared(name)) ? hubPoint->target = newTarget : hubPoint->target = visitedTarget;
539                                 
540                                 hubList.add(hubPoint);
541                                 numberOfHubs++;
542                         }
543                 }
544
545                 line = strtok(NULL, "\n");
546         }
547
548         int rtn = -1;
549         
550         strlcpy(level, "@none@", sizeof level);
551         strlcpy(game.stageName, "@none@", sizeof game.stageName);
552
553         bool showData = false;
554         bool showStats = false;
555         bool showMIAs = false;
556         
557         int miaStart = 0;
558         int miaMax = 0;
559         int page = 0;
560         
561         int labelX, labelY;
562
563         Data *data = (Data*)gameData.dataList.getHead();
564
565         while (data->next != NULL)
566         {
567                 data = (Data*)data->next;
568
569                 if (strstr(data->value, "MIA_"))
570                 {
571                         miaMax++;
572                 }
573         }
574         
575         bool validStage = false;
576         
577         if ((numberOfHubs == 0) && (gameData.completedWorld))
578         {
579                 game.setMapName("data/spaceStation");
580                 strlcpy(game.stageName, "Space Station", sizeof game.stageName);
581                 createObjectivesPanel("Space Station");
582                 showData = true;
583                 showStats = showMIAs = false;
584                 validStage = true;
585                 
586                 // Wait wait wait... we're in easy mode. Game ends here.
587                 if (game.skill == 0)
588                 {
589                         hubList.clear();
590                         return SECTION_EASYOVER;
591                 }
592                 
593                 presentPlayerMedal("World_Complete");
594         }
595         
596         audio.playMusic();
597
598         int labelWidth = 0;
599         Uint32 frameLimit = SDL_GetTicks() + 16;
600         Uint32 now = SDL_GetTicks();
601         
602         int mouseXDelta = 0;
603         int mouseYDelta = 0;
604
605         while (rtn == -1)
606         {
607                 graphics.updateScreen();
608                 graphics.drawBackground();
609                 graphics.animateSprites();
610
611                 if (validStage)
612                 {
613                         static Graphics::SurfaceCache cache;
614                         graphics.drawRect(10, 400, 620, 20, graphics.black, graphics.white, graphics.screen);
615                         snprintf(string, sizeof string, "%s : %s", _("Selected Destination"), _(game.stageName));
616                         graphics.drawString(string, 320, 409, true, graphics.screen, cache);
617                 }
618                 
619                 graphics.drawRect(10, 430, 620, 40, graphics.black, graphics.white, graphics.screen);
620
621                 #if DEBUG
622                 static Graphics::SurfaceCache posCache;
623                 snprintf(pos, sizeof pos, "%.3d:%.3d", engine.getMouseX(), engine.getMouseY());
624                 graphics.drawString(pos, 320, 15, true, graphics.screen, posCache);
625                 #endif
626
627                 engine.getInput();
628                 config.populate();
629                 
630                 if (config.isControl(CONTROL::RIGHT))
631                 {
632                         mouseXDelta = 5;
633                 }
634                 
635                 if (config.isControl(CONTROL::LEFT))
636                 {
637                         mouseXDelta = -5;
638                 }
639                 
640                 if (config.isControl(CONTROL::DOWN))
641                 {
642                         mouseYDelta = 5;
643                 }
644                 
645                 if (config.isControl(CONTROL::UP) || config.isControl(CONTROL::JUMP))
646                 {
647                         mouseYDelta = -5;
648                 }
649
650                 if ((mouseXDelta != 0) || (mouseYDelta != 0))
651                 {
652                         engine.setMouse(engine.getMouseX() + (int)mouseXDelta, engine.getMouseY() + (int)mouseYDelta);
653                         mouseXDelta = 0;
654                         mouseYDelta = 0;
655                 }
656
657                 hubPoint = (HubLevel*)hubList.getHead();
658
659                 // Collisions for Hub Points
660                 while (hubPoint->next != NULL)
661                 {
662                         hubPoint = (HubLevel*)hubPoint->next;
663
664                         graphics.blit(hubPoint->target->getCurrentFrame(), hubPoint->x, hubPoint->y, graphics.screen, false);
665
666                         if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, hubPoint->x, hubPoint->y, 16, 16))
667                         {
668                                 labelX = engine.getMouseX();
669                                 labelY = engine.getMouseY() - 20;
670
671                                 labelWidth = hubPoint->levelNameImage->w / 2;
672
673                                 Math::limitInt(&labelX, 10 + labelWidth, 630 - labelWidth);
674
675                                 graphics.blit(hubPoint->levelNameImage, labelX, labelY, graphics.screen, true);
676
677                                 if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
678                                 {
679                                         game.setMapName(hubPoint->filename);
680                                         game.setStageName(hubPoint->stageName);
681                                         validStage = true;
682                                         engine.mouseLeft = 0;
683                                         config.resetControl(CONTROL::FIRE);
684                                 }
685
686                                 if (engine.mouseRight || config.isControl(CONTROL::MAP))
687                                 {
688                                         game.setMapName(hubPoint->filename);
689                                         game.setStageName(hubPoint->stageName);
690                                         createObjectivesPanel(game.stageName);
691                                         showData = true;
692                                         showStats = false;
693                                         engine.mouseRight = 0;
694                                         config.resetControl(CONTROL::MAP);
695                                 }
696                         }
697                 }
698
699                 // Collisions for Panel
700                 for (int i = ((1 - validStage) * 2) ; i < 6 ; i++)
701                 {
702                         graphics.blit(hubIcons->image[i], 50 + (i * 100), 440, graphics.screen, false);
703                         if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, 50 + (i * 100), 440, hubIcons->image[i]->w, hubIcons->image[i]->h))
704                         {
705                                 if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
706                                 {
707                                         switch (i)
708                                         {
709                                                 case 0:
710                                                         rtn = SECTION_GAME;
711                                                         break;
712                                                 case 1:
713                                                         createObjectivesPanel(game.stageName);
714                                                         showData = !showData;
715                                                         showStats = showMIAs = false;
716                                                         break;
717                                                 case 2:
718                                                         createMIAPanel(miaStart, miaMax);
719                                                         showStats = showData = false;
720                                                         showMIAs = !showMIAs;
721                                                         break;
722                                                 case 3:
723                                                         createStatsPanel(page);
724                                                         showStats = !showStats;
725                                                         showData = showMIAs = false;
726                                                         break;
727                                                 case 4:
728                                                         showOptions();
729                                                         graphics.setFontSize(0);
730                                                         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
731                                                         break;
732                                                 case 5:
733                                                         rtn = SECTION_TITLE;
734                                                         break;
735                                         }
736
737                                         engine.mouseLeft = false;
738                                         config.resetControl(CONTROL::FIRE);
739                                 }
740                         }
741                 }
742                 
743                 // Collisions for Panel Buttons
744                 if ((showMIAs) || (showStats))
745                 {
746                     // SDL_SCANCODE_LCTRL is the "fire" button.
747                         if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
748                         {
749                                 if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, 270, 310, 32, 32))
750                                 {
751                                         if (showMIAs)
752                                         {
753                                                 if (miaStart > 0)
754                                                 {
755                                                         Math::limitInt(&(miaStart -= 9), 0, miaMax);
756                                                         createMIAPanel(miaStart, miaMax);
757                                                 }
758                                         }
759
760                                         if (showStats)
761                                         {
762                                                 Math::limitInt(&(--page), 0, 2);
763                                                 createStatsPanel(page);
764                                         }
765
766                                         engine.mouseLeft = 0;
767                                         config.resetControl(CONTROL::FIRE);
768                                 }
769
770
771                                 if (Collision::collision(engine.getMouseX(), engine.getMouseY(), 1, 1, 320, 310, 32, 32))
772                                 {
773                                         if (showMIAs)
774                                         {
775                                                 if (miaStart + 9 < miaMax)
776                                                 {
777                                                         Math::limitInt(&(miaStart += 9), 0, miaMax);
778                                                         createMIAPanel(miaStart, miaMax);
779                                                 }
780                                         }
781
782                                         if (showStats)
783                                         {
784                                                 Math::limitInt(&(++page), 0, 2);
785                                                 createStatsPanel(page);
786                                         }
787
788                                         engine.mouseLeft = 0;
789                                         config.resetControl(CONTROL::FIRE);
790                                 }
791                         }
792                 }
793
794                 if ((showData) || (showStats) || (showMIAs))
795                 {
796                         graphics.blit(infoPanel, 320, 200, graphics.screen, true);
797                         if (engine.mouseLeft || config.isControl(CONTROL::FIRE))
798                         {
799                                 showData = showStats = showMIAs = false;
800                         }
801                 }
802
803                 graphics.blit(cursor->getCurrentFrame(), engine.getMouseX(), engine.getMouseY(), graphics.screen, true);
804
805                 doMusicInfo(SDL_GetTicks() - (now + 60000));
806                 engine.delay(frameLimit);
807                 frameLimit = SDL_GetTicks() + 16;
808         }
809
810         hubList.clear();
811
812         return rtn;
813 }