]> git.mxchange.org Git - quix0rs-blobwars.git/blob - src/info.cpp
Fix reading one element past the end of an array.
[quix0rs-blobwars.git] / src / info.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 "info.h"
23
24 void doTimeRemaining()
25 {               
26         map.remainingSeconds--;
27         
28         if ((map.remainingMinutes == 0) && (map.remainingSeconds <= 10) && (map.remainingSeconds > 0))
29         {
30                 audio.playSound(SND_CLOCK, CH_TOUCH);
31         }
32         
33         if (map.remainingSeconds < 0)
34         {
35                 if (map.remainingMinutes > 0)
36                 {
37                         map.remainingSeconds = 59;
38                         map.remainingMinutes--;
39                 }
40         }
41         
42         if ((map.remainingSeconds == 0) && (map.remainingMinutes == 0))
43         {
44                 player.health = 0;
45                 player.immune = 0;
46                 Math::removeBit(&player.flags, ENT_FLIES);
47                 game.setMissionOver(MIS_TIMEUP);
48         }
49         
50         replayData.header.time++;
51 }
52
53 void doStatusBar()
54 {
55         static Graphics::SurfaceCache healthCache;
56         static Graphics::SurfaceCache oxygenCache;
57         static Graphics::SurfaceCache jetpackCache;
58
59         graphics.setFontSize(0);
60         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
61
62         char string[1024];
63
64         graphics.blit(graphics.infoBar, 0, 0, graphics.screen, false);
65
66         graphics.drawString(_("Health"), 50, 5, TXT_RIGHT, graphics.screen, healthCache);
67
68         for (int i = 0 ; i < MAX_HEALTH ; i++)
69         {
70                 if (i < player.health)
71                         graphics.blit(graphics.getSprite("HealthBlock", true)->getCurrentFrame(), 60 + (i * 15), 7, graphics.screen, false);
72                 else
73                         graphics.blit(graphics.getSprite("HealthBlockEmpty", true)->getCurrentFrame(), 60 + (i * 15), 7, graphics.screen, false);
74         }
75
76         if (player.health <= 3)
77                 if (engine.getFrameLoop() < 30)
78                         for (int i = 0 ; i < player.health ; i++)
79                                 graphics.blit(graphics.getSprite("WarningBlock", true)->getCurrentFrame(), 60 + (i * 15), 7, graphics.screen, false);
80
81         if ((!game.hasAquaLung) && (!engine.cheatExtras))
82         {
83                 graphics.drawString(_("Oxygen"), 305, 5, TXT_RIGHT, graphics.screen, oxygenCache);
84
85                 for (int i = 0 ; i < 7 ; i++)
86                 {
87                         if (i < player.oxygen)
88                                 graphics.blit(graphics.getSprite("OxygenBlock", true)->getCurrentFrame(), 315 + (i * 15), 7, graphics.screen, false);
89                         else
90                                 graphics.blit(graphics.getSprite("OxygenBlockEmpty", true)->getCurrentFrame(), 315 + (i * 15), 7, graphics.screen, false);
91                 }
92
93                 if (player.oxygen <= 3)
94                         if (engine.getFrameLoop() < 30)
95                                 for (int i = 0 ; i < player.oxygen ; i++)
96                                         graphics.blit(graphics.getSprite("WarningBlock", true)->getCurrentFrame(), 315 + (i * 15), 7, graphics.screen, false);
97         }
98         else if ((game.hasJetPack) || (engine.cheatExtras))
99         {
100                 graphics.drawString(_("Jetpack"), 305, 5, TXT_RIGHT, graphics.screen, jetpackCache);
101
102                 for (int i = 0 ; i < 7 ; i++)
103                 {
104                         if (i < player.fuel)
105                                 graphics.blit(graphics.getSprite("OxygenBlock", true)->getCurrentFrame(), 315 + (i * 15), 7, graphics.screen, false);
106                         else
107                                 graphics.blit(graphics.getSprite("OxygenBlockEmpty", true)->getCurrentFrame(), 315 + (i * 15), 7, graphics.screen, false);
108                 }
109
110                 if ((player.fuel < 3) && (!(player.flags & ENT_FLIES)))
111                         if (engine.getFrameLoop() < 30)
112                                 for (int i = 0 ; i < player.fuel ; i++)
113                                         graphics.blit(graphics.getSprite("WarningBlock", true)->getCurrentFrame(), 315 + (i * 15), 7, graphics.screen, false);
114         }
115
116         if ((map.mainBossPart == NULL || strstr(engine.message, "Aqua") || strstr(engine.message, "Jet")) && (game.missionOverReason != MIS_GAMECOMPLETE))
117         {
118                 if (engine.messageTime > -1)
119                 {
120                         switch (engine.messageType)
121                         {
122                                 case INFO_NORMAL:
123                                         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
124                                         break;
125                                 case INFO_OBJECTIVE:
126                                         graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
127                                         break;
128                                 case INFO_HINT:
129                                         graphics.setFontColor(0xff, 0xaa, 0x00, 0x00, 0x00, 0x00);
130                                         break;
131                                 case INFO_ACTIVATE:
132                                         graphics.setFontColor(0x00, 0xff, 0xff, 0x00, 0x00, 0x00);
133                                         break;
134                                 case INFO_BAD:
135                                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
136                                         break;
137                         }
138         
139                         static Graphics::SurfaceCache cache;
140                         graphics.blit(graphics.infoBar, 0, 455, graphics.screen, false);
141                         graphics.drawString(_(engine.message), 320, 466, true, graphics.screen, cache);
142                         
143                         engine.messageTime--;
144                         if (engine.messageTime == -1)
145                         {
146                                 engine.messagePriority = -1;
147                                 engine.message[0] = 0;
148                         }
149         
150                         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
151                 }
152         }
153         else
154         {
155                 if (map.mainBossPart != NULL)
156                 {
157                         graphics.blit(graphics.infoBar, 0, 455, graphics.screen, false);
158                         
159                         static Graphics::SurfaceCache cache;
160                         graphics.drawString(_(map.mainBossPart->name), 255, 460, TXT_RIGHT, graphics.screen, cache);
161                         graphics.drawRect(265 - 1, 463 - 1, 200 + 2, 10 + 2, graphics.white, graphics.screen);
162                         graphics.drawRect(265, 463, 200, 10, graphics.black, graphics.screen);
163                         
164                         if (map.mainBossPart->health > 0)
165                         {
166                                 graphics.drawRect(265, 463, (int)(map.mainBossPart->health * map.bossEnergyMeterBit), 10, graphics.red, graphics.screen);
167                         }
168                 }
169         }
170
171         static Graphics::SurfaceCache weaponCache;
172         snprintf(string, sizeof string, "%s %s", _("Weapon:"), _(player.currentWeapon->name));
173         graphics.drawString(string, 630, 5, TXT_RIGHT, graphics.screen, weaponCache);
174         
175         if (game.skill == 3)
176         {
177                 snprintf(string, sizeof string, _("Time Remaining: %.2d:%.2d"), map.remainingMinutes, map.remainingSeconds);
178                 graphics.blit(graphics.infoBar, 0, 25, graphics.screen, false);
179                 
180                 if ((map.remainingMinutes > 0) || (map.remainingSeconds > 0))
181                 {
182                         if (map.remainingMinutes == 0)
183                         {
184                                 if (map.remainingSeconds > 0)
185                                 {
186                                         if (map.remainingSeconds <= 10)
187                                         {
188                                                 graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
189                                         }
190                                         else if (map.remainingSeconds <= 30)
191                                         {
192                                                 graphics.setFontColor(0xff, 0xff, 0x00, 0x00, 0x00, 0x00);
193                                         }
194                                 }
195                         }
196                         static Graphics::SurfaceCache cache;
197                         graphics.drawString(string, 320, 35, TXT_CENTERED, graphics.screen, cache);
198                 }
199                 else
200                 {
201                         static Graphics::SurfaceCache cache;
202                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
203                         graphics.setFontSize(3);
204                         graphics.drawString(_("Mission Failed! Time Up!"), 320, 220, TXT_CENTERED, graphics.screen, cache);
205                         graphics.setFontSize(0);
206                         game.canContinue = 0;
207                 }
208         }
209 }
210
211 void doPauseInfo()
212 {
213         int col1, col2, y;
214
215         col1 = 310;
216         col2 = 330;
217         y = 60;
218
219         graphics.fade(130);
220
221         char string[1024];
222         string[0] = 0;
223         
224         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
225
226         #if DEBUG
227         snprintf(string, sizeof string, _("Position = %d:%d"), (int)player.x, (int)player.y);
228         graphics.drawString(string, 5, 25, false, graphics.screen);
229         #endif
230
231         graphics.drawString(_("*** PAUSED ***"), 320, y, TXT_CENTERED, graphics.screen);
232
233         graphics.drawString(_("MIAs in Area"), col1, y += 30, TXT_RIGHT, graphics.screen);
234         snprintf(string, sizeof string, "%d", map.totalMIAs - map.foundMIAs);
235         graphics.drawString(string, col2, y, TXT_LEFT, graphics.screen);
236
237         graphics.drawString(_("Enemies Defeated"), col1, y += 20, TXT_RIGHT, graphics.screen);
238         snprintf(string, sizeof string, "%d", game.currentMissionEnemiesDefeated);
239         graphics.drawString(string, col2, y, TXT_LEFT, graphics.screen);
240
241         graphics.drawString(_("Items Collected"), col1, y += 20, TXT_RIGHT, graphics.screen);
242         snprintf(string, sizeof string, "%d / %d", map.foundItems, map.totalItems);
243         graphics.drawString(string, col2, y, TXT_LEFT, graphics.screen);
244
245         graphics.drawString(_("Best Combo"), col1, y += 20, TXT_RIGHT, graphics.screen);
246         snprintf(string, sizeof string, _("%d Hits"), game.maxComboHits);
247         graphics.drawString(string, col2, y, TXT_LEFT, graphics.screen);
248
249         graphics.drawString(_("++ Inventory ++"), 320, y += 40, TXT_CENTERED, graphics.screen);
250         showCarriedItems();
251
252         // Do the objectives list
253         Objective *objective = (Objective*)map.objectiveList.getHead();
254         char message[256];
255
256         y += 60;
257
258         if (map.totalMIAs > 0)
259         {
260                 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
261                 snprintf(message, sizeof message, _("Rescue %d MIAs"), map.requiredMIAs);
262                 graphics.drawString(message, col1, y, TXT_RIGHT, graphics.screen);
263
264                 if (map.foundMIAs < map.requiredMIAs)
265                 {
266                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
267                         snprintf(message, sizeof message, "%d / %d", map.foundMIAs, map.requiredMIAs);
268                         graphics.drawString(message, col2, y, TXT_LEFT, graphics.screen);
269                 }
270                 else
271                 {
272                         graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
273                         graphics.drawString(_("Completed"), col2, y, TXT_LEFT, graphics.screen);
274                 }
275         }
276
277         while (objective->next != NULL)
278         {
279                 objective = (Objective*)objective->next;
280
281                 y += 20;
282                 
283                 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
284                 
285                 if ((game.skill < 3) &&  (strstr(objective->description, "L.R.T.S.")) && (!gameData.completedWorld))
286                 {
287                         graphics.drawString(_("???? ???????? ????"), col1, y, TXT_RIGHT, graphics.screen);
288                 }
289                 else
290                 {
291                         graphics.drawString(_(objective->description), col1, y, TXT_RIGHT, graphics.screen);
292                 }
293                 
294                 // this is a fake objective (for the 4th Ancient Tomb)
295                 if (objective->targetValue == -1)
296                 {
297                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
298                         graphics.drawString(_("Incomplete"), col2, y, TXT_LEFT, graphics.screen);
299                 }
300                 else if (objective->currentValue < objective->targetValue)
301                 {
302                         graphics.setFontColor(0xff, 0x00, 0x00, 0x00, 0x00, 0x00);
303                         if (objective->targetValue == 1)
304                         {
305                                 graphics.drawString(_("Incomplete"), col2, y, TXT_LEFT, graphics.screen);
306                         }
307                         else
308                         {
309                                 snprintf(message, sizeof message, "%d / %d", objective->currentValue, objective->targetValue);
310                         graphics.drawString(message, col2, y, TXT_LEFT, graphics.screen);
311                         }
312
313                         if (!objective->required)
314                         {
315                                 graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
316                                 graphics.drawString(_("(optional)"), 450, y, TXT_LEFT, graphics.screen);
317                         }
318                 }
319                 else
320                 {
321                         graphics.setFontColor(0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
322                         graphics.drawString(_("Completed"), col2, y, TXT_LEFT, graphics.screen);
323                 }
324         }
325
326         graphics.setFontColor(0xff, 0xff, 0xff, 0x00, 0x00, 0x00);
327
328         y += 10;
329
330         snprintf(string, sizeof string, "%s - %.2d:%.2d:%.2d", _("Mission Time"), game.currentMissionHours, game.currentMissionMinutes, game.currentMissionSeconds);
331         graphics.drawString(string, 320, 430, TXT_CENTERED, graphics.screen);
332 }
333
334 SDL_Surface *createMusicInfo(void)
335 {
336         graphics.setFontSize(0);
337         graphics.setFontColor(0xff, 0xff, 0xff, 0x40, 0x40, 0x40);
338
339         SDL_Surface *text1;
340         SDL_Surface *text2 = NULL;
341         SDL_Surface *text3 = NULL;
342         SDL_Surface *icon;
343         SDL_Surface *panel;
344
345         int w = 0;
346         int h = 0;
347
348         text1 = graphics.getString(audio.songtitle, true);
349         h = text1->h;
350         w = text1->w;
351
352         if(audio.songalbum[0])
353         {
354                 graphics.setFontColor(0x80, 0xc0, 0xff, 0x40, 0x40, 0x40);
355                 
356                 text2 = graphics.getString(audio.songalbum, true);
357                 h += text2->h + 4;
358                 if(text2->w > w)
359                         w = text2->w;
360
361         }
362
363         if(audio.songartist[0])
364         {
365                 graphics.setFontColor(0xff, 0xc0, 0x80, 0x40, 0x40, 0x40);
366
367                 text3 = graphics.getString(audio.songartist, true);
368                 h += text3->h + 4;
369                 if(text3->w > w)
370                         w = text3->w;
371         }
372
373         if(audio.songlicense >= 0)
374         {
375                 icon = graphics.license[audio.songlicense];
376
377                 h += icon->h + 8;
378                 if(icon->w > w)
379                         w = icon->w;
380         }
381
382         int y = h + 5;
383         int x = w + 5;
384
385         panel = graphics.createSurface(w + 10, h + 10);
386         SDL_FillRect(panel, NULL, SDL_MapRGBA(panel->format, 0, 0, 0, 128));
387
388         if (text1) {
389                 y -= text1->h;
390                 graphics.blit(text1, x - text1->w, y, panel, false);
391                 SDL_FreeSurface(text1);
392         }
393
394         if (text2) {
395                 y -= text2->h + 4;
396                 graphics.blit(text2, x - text2->w, y, panel, false);
397                 SDL_FreeSurface(text2);
398         }
399
400         if (text3) {
401                 y -= text3->h + 4;
402                 graphics.blit(text3, x - text3->w, y, panel, false);
403                 SDL_FreeSurface(text3);
404         }
405
406         if (icon) {
407                 y -= icon->h + 8;
408                 graphics.blit(icon, x - icon->w, y, panel, false);
409         }
410
411         return panel;
412 }
413
414 void doMusicInfo(unsigned int ticks)
415 {
416         if(!audio.songtitle[0])
417                 return;
418
419         static SDL_Surface *panel;
420         float alpha = 1;
421
422         if (ticks != -1U)
423         {
424                 if (ticks > 12000 || ticks < 5000)
425                 {
426                         if (panel)
427                         {
428                                 SDL_FreeSurface(panel);
429                                 panel = NULL;
430                         }
431
432                         return;
433                 }
434
435                 if(ticks < 6000)
436                         alpha = 1 - (6000 - ticks) / 1000.0f;
437                 else if(ticks > 11000)
438                         alpha = (12000 - ticks) / 1000.0f;
439         }
440
441         if (alpha > 0.99)
442                 alpha = 0.99;
443
444         if (!panel)
445                 panel = createMusicInfo();
446         if (!panel)
447                 return;
448
449         SDL_SetAlpha(panel, 255 * alpha);
450         graphics.blit(panel, 620 - panel->w, 420 - panel->h, graphics.screen, false);
451 }