FS2_Open
Open source remastering of the Freespace 2 engine
medals.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include "debugconsole/console.h"
15 #include "gamesnd/gamesnd.h"
16 #include "globalincs/alphacolors.h"
17 #include "io/key.h"
18 #include "localization/localize.h"
19 #include "menuui/snazzyui.h"
20 #include "palman/palman.h"
21 #include "parse/parselo.h"
22 #include "playerman/player.h"
23 #include "stats/medals.h"
24 #include "ui/ui.h"
25 
26 #ifndef NDEBUG
27 #include "cmdline/cmdline.h"
28 #endif
29 
30 int Num_medals = 0;
31 
32 // define for the medal information
34 
35 // coords for indiv medal bitmaps
36 static int Default_medal_coords[GR_NUM_RESOLUTIONS][NUM_MEDALS_FS2][2] = {
37  { // GR_640
38  { 89, 47 }, // eps. peg. lib
39  { 486, 47 }, // imp. order o' vasuda
40  { 129, 130 }, // dist flying cross
41  { 208, 132 }, // soc service
42  { 361, 131 }, // dist intel cross
43  { 439, 130 }, // order of galatea
44  { 64, 234 }, // meritorious unit comm.
45  { 153, 234 }, // medal of valor
46  { 239, 241 }, // gtva leg of honor
47  { 326, 240 }, // allied defense citation
48  { 411, 234 }, // neb campaign victory
49  { 494, 234 }, // ntf campaign victory
50  { 189, 80 }, // rank
51  { 283, 91 }, // wings
52  { 372, 76 }, // bronze kills badge
53  { 403, 76 }, // silver kills badge
54  { 435, 76 }, // gold kills badge
55  { 300, 152 }, // SOC unit crest
56  },
57  { // GR_1024
58  { 143, 75 }, // eps. peg. lib
59  { 777, 75 }, // imp. order o' vasuda
60  { 206, 208 }, // dist flying cross
61  { 333, 212 }, // soc service
62  { 578, 210 }, // dist intel cross
63  { 703, 208 }, // order of galatea
64  { 103, 374 }, // meritorious unit comm.
65  { 245, 374 }, // medal of valor
66  { 383, 386 }, // gtva leg of honor
67  { 522, 384 }, // allied defense citation
68  { 658, 374 }, // neb campaign victory
69  { 790, 374 }, // ntf campaign victory
70  { 302, 128 }, // rank
71  { 453, 146 }, // wings
72  { 595, 121 }, // bronze kills badge
73  { 646, 121 }, // silver kills badge
74  { 696, 121 }, // gold kills badge
75  { 480, 244 }, // SOC unit crest
76  }
77 };
78 
79 // debriefing bitmaps
80 static const char *Default_debriefing_bitmaps[NUM_MEDALS_FS2] =
81 {
82  "DebriefMedal00",
83  "DebriefMedal01",
84  "DebriefMedal02",
85  "DebriefMedal03",
86  "DebriefMedal04",
87  "DebriefMedal05",
88  "DebriefMedal06",
89  "DebriefMedal07",
90  "DebriefMedal08",
91  "DebriefMedal09",
92  "DebriefMedal10",
93  "DebriefMedal11",
94  "DebriefRank##",
95  "DebriefWings##",
96  "DebriefBadge01",
97  "DebriefBadge02",
98  "DebriefBadge03",
99  "DebriefCrest"
100 };
101 
102 // argh
103 typedef struct coord2dw {
104  int x,y,w;
105 } coord2dw;
106 
107 // coords for the medal title
108 static int Default_medals_label_coords[GR_NUM_RESOLUTIONS][3] = {
109  { 241, 458, 300 }, // GR_640 x, y, w
110  { 386, 734, 480 } // GR_1024 x, y, w
111 };
112 static coord2dw Medals_label_coords[GR_NUM_RESOLUTIONS];
113 
114 // coords for the player callsign
115 static int Default_medals_callsign_coords[GR_NUM_RESOLUTIONS][2] = {
116  { -1, 54 }, // we'll use -1 as a convention to center it
117  { -1, 89 }
118 };
119 static coord2d Medals_callsign_coords[GR_NUM_RESOLUTIONS];
120 
121 #define MEDALS_NUM_BUTTONS 1
122 #define MEDALS_EXIT 0
124  { // GR_640
125  ui_button_info("MEB_18", 574, 432, -1, -1, 18),
126  },
127  { // GR_1024
128  ui_button_info("2_MEB_18", 919, 691, -1, -1, 18),
129  }
130 };
131 
132 #define MEDALS_NUM_TEXT 1
134  { // GR_640
135  {"Exit", 1466, 587, 416, UI_XSTR_COLOR_PINK, -1, &Medals_buttons[GR_640][MEDALS_EXIT].button },
136  },
137  { // GR_1024
138  {"Exit", 1466, 943, 673, UI_XSTR_COLOR_PINK, -1, &Medals_buttons[GR_1024][MEDALS_EXIT].button },
139  },
140 };
141 
142 static const char* Default_medals_background_filename = "MedalsDisplayEmpty";
143 static char Medals_background_filename[NAME_LENGTH];
144 
145 static const char* Default_medals_mask_filename = "Medals-M";
146 static char Medals_mask_filename[NAME_LENGTH];
147 
149 
152 
153 void init_medal_bitmaps();
154 void init_snazzy_regions();
155 void blit_medals();
156 
157 // -----------------------------------------------------------------------------
158 // Main medals screen state
159 //
160 
161 static bitmap *Medals_mask;
163 static int Medals_bitmap_mask; // the mask for the medal case
164 static int Medals_bitmap; // the medal case itself
165 static int Rank_bm; // bitmap for the rank medal
166 
167 static UI_WINDOW Medals_window;
168 
169 typedef struct medal_display_info {
170  int bitmap; // image in the medal case
171  coord2d coords[GR_NUM_RESOLUTIONS]; // screen position (can now be defined by the table)
173 
174 static SCP_vector<medal_display_info> Medal_display_info;
175 static MENU_REGION *Medal_regions = NULL;
176 
178 
179 
180 #define MEDAL_BITMAP_INIT (1<<0)
181 #define MASK_BITMAP_INIT (1<<1)
183 
185  : num_versions(1), version_starts_at_1(false), available_from_start(false), kills_needed(0), promotion_text()
186 {
187  name[0] = '\0';
188  bitmap[0] = '\0';
189  debrief_bitmap[0] = '\0';
190  voice_base[0] = '\0';
191 }
192 
194 {
196  for (it = promotion_text.begin(); it != promotion_text.end(); ++it) {
197  if (it->second) {
198  vm_free(it->second);
199  }
200  }
201  promotion_text.clear();
202 }
203 
205 {
206  clone(m);
207 }
208 
209 void medal_stuff::clone(const medal_stuff &m)
210 {
211  memcpy(name, m.name, NAME_LENGTH);
212  memcpy(bitmap, m.bitmap, MAX_FILENAME_LEN);
219 
220  promotion_text.clear();
222  for (it = m.promotion_text.begin(); it != m.promotion_text.end(); ++it) {
223  if (it->second) {
224  promotion_text[it->first] = vm_strdup(it->second);
225  }
226  }
227 }
228 
229 // assignment operator
231 {
232  if (this != &m) {
234  for (it = promotion_text.begin(); it != promotion_text.end(); ++it) {
235  if (it->second) {
236  vm_free(it->second);
237  }
238  }
239  promotion_text.clear();
240  clone(m);
241  }
242 
243  return *this;
244 }
245 
247 {
248  int i;
249 
250  try
251  {
252  read_file_text("medals.tbl", CF_TYPE_TABLES);
253  reset_parse();
254 
255  required_string("#Medals");
256 
257  // special background information
258  if (optional_string("+Background Bitmap:")) {
259  stuff_string(Medals_background_filename, F_NAME, NAME_LENGTH);
260  }
261  else {
262  strcpy_s(Medals_background_filename, Default_medals_background_filename);
263  }
264 
265  // special mask information
266  if (optional_string("+Mask Bitmap:")) {
267  stuff_string(Medals_mask_filename, F_NAME, NAME_LENGTH);
268  }
269  else {
270  strcpy_s(Medals_mask_filename, Default_medals_mask_filename);
271  }
272 
273  // special positioning for player callsign
274  if (optional_string("+Callsign Position 640:")) {
275  stuff_int(&Medals_callsign_coords[GR_640].x);
276  stuff_int(&Medals_callsign_coords[GR_640].y);
277  }
278  else {
279  Medals_callsign_coords[GR_640].x = Default_medals_callsign_coords[GR_640][0];
280  Medals_callsign_coords[GR_640].y = Default_medals_callsign_coords[GR_640][1];
281  }
282  if (optional_string("+Callsign Position 1024:")) {
283  stuff_int(&Medals_callsign_coords[GR_1024].x);
284  stuff_int(&Medals_callsign_coords[GR_1024].y);
285  }
286  else {
287  Medals_callsign_coords[GR_1024].x = Default_medals_callsign_coords[GR_1024][0];
288  Medals_callsign_coords[GR_1024].y = Default_medals_callsign_coords[GR_1024][1];
289  }
290 
291  // special positioning for medal label
292  if (optional_string("+Label Position 640:")) {
293  stuff_int(&Medals_label_coords[GR_640].x);
294  stuff_int(&Medals_label_coords[GR_640].y);
295  stuff_int(&Medals_label_coords[GR_640].w);
296  }
297  else {
298  Medals_label_coords[GR_640].x = Default_medals_label_coords[GR_640][0];
299  Medals_label_coords[GR_640].y = Default_medals_label_coords[GR_640][1];
300  Medals_label_coords[GR_640].w = Default_medals_label_coords[GR_640][2];
301  }
302  if (optional_string("+Label Position 1024:")) {
303  stuff_int(&Medals_label_coords[GR_1024].x);
304  stuff_int(&Medals_label_coords[GR_1024].y);
305  stuff_int(&Medals_label_coords[GR_1024].w);
306  }
307  else {
308  Medals_label_coords[GR_1024].x = Default_medals_label_coords[GR_1024][0];
309  Medals_label_coords[GR_1024].y = Default_medals_label_coords[GR_1024][1];
310  Medals_label_coords[GR_1024].w = Default_medals_label_coords[GR_1024][2];
311  }
312 
313  // parse in all the medal names
314  Num_medals = 0;
315  while (required_string_either("#End", "$Name:"))
316  {
317  medal_stuff temp_medal;
318  medal_display_info temp_display;
319 
320  required_string("$Name:");
321  stuff_string(temp_medal.name, F_NAME, NAME_LENGTH);
322 
323  // is this rank? if so, save it
324  if (!stricmp(temp_medal.name, "Rank"))
326 
327  required_string("$Bitmap:");
329 
330  if (optional_string("+Position 640:")) {
331  stuff_int(&temp_display.coords[GR_640].x);
332  stuff_int(&temp_display.coords[GR_640].y);
333  }
334  else if (Num_medals < NUM_MEDALS_FS2) {
335  temp_display.coords[GR_640].x = Default_medal_coords[GR_640][Num_medals][0];
336  temp_display.coords[GR_640].y = Default_medal_coords[GR_640][Num_medals][1];
337  }
338  else {
339  Warning(LOCATION, "No default GR_640 position for medal '%s'!", temp_medal.name);
340  temp_display.coords[GR_640].x = 0;
341  temp_display.coords[GR_640].y = 0;
342  }
343  if (optional_string("+Position 1024:")) {
344  stuff_int(&temp_display.coords[GR_1024].x);
345  stuff_int(&temp_display.coords[GR_1024].y);
346  }
347  else if (Num_medals < NUM_MEDALS_FS2) {
348  temp_display.coords[GR_1024].x = Default_medal_coords[GR_1024][Num_medals][0];
349  temp_display.coords[GR_1024].y = Default_medal_coords[GR_1024][Num_medals][1];
350  }
351  else {
352  Warning(LOCATION, "No default GR_1024 position for medal '%s'!", temp_medal.name);
353  temp_display.coords[GR_1024].x = 0;
354  temp_display.coords[GR_1024].y = 0;
355  }
356 
357  if (optional_string("+Debriefing Bitmap:")) {
359  }
360  else if (Num_medals < NUM_MEDALS_FS2) {
361  strcpy_s(temp_medal.debrief_bitmap, Default_debriefing_bitmaps[Num_medals]);
362  }
363  else {
364  Warning(LOCATION, "No default debriefing bitmap for medal '%s'!", temp_medal.name);
365  strcpy_s(temp_medal.debrief_bitmap, "");
366  }
367 
368  required_string("$Num mods:");
369  stuff_int(&temp_medal.num_versions);
370 
371  // this is dumb
373  if (optional_string("+Version starts at 1:")) {
374  stuff_boolean(&temp_medal.version_starts_at_1);
375  }
376 
377  if (optional_string("+Available From Start:")) {
378  stuff_boolean(&temp_medal.available_from_start);
379  }
380 
381  // some medals are based on kill counts. When string +Num Kills: is present, we know that
382  // this medal is a badge and should be treated specially
383  if (optional_string("+Num Kills:")) {
384  char buf[MULTITEXT_LENGTH];
385  int persona;
386  stuff_int(&temp_medal.kills_needed);
387 
388  if (optional_string("$Wavefile 1:"))
390 
391  if (optional_string("$Wavefile 2:"))
393 
394  if (optional_string("$Wavefile Base:"))
396 
397  while (check_for_string("$Promotion Text:")) {
398  required_string("$Promotion Text:");
399  stuff_string(buf, F_MULTITEXT, sizeof(buf));
400  persona = -1;
401  if (optional_string("+Persona:")) {
402  stuff_int(&persona);
403  if (persona < 0) {
404  Warning(LOCATION, "Debriefing text for %s is assigned to an invalid persona: %i (must be 0 or greater).\n", temp_medal.name, persona);
405  continue;
406  }
407  }
408  temp_medal.promotion_text[persona] = vm_strdup(buf);
409  }
410  if (temp_medal.promotion_text.find(-1) == temp_medal.promotion_text.end()) {
411  Warning(LOCATION, "%s medal is missing default debriefing text.\n", temp_medal.name);
412  temp_medal.promotion_text[-1] = "";
413  }
414  }
415 
416  Medals.push_back(temp_medal);
417  Medal_display_info.push_back(temp_display);
418  Num_medals++;
419  }
420 
421  required_string("#End");
422 
423  // be sure that we know where the rank is
424  if (Rank_medal_index < 0)
425  {
426  Warning(LOCATION, "Could not find the 'Rank' medal!");
427  Rank_medal_index = 0;
428  }
429 
430  // be sure that the badges kill numbers show up in order
431  //WMC - I don't think this is needed anymore due to my changes to post-mission functions
432  //but I'm keeping it here to be sure.
433  int prev_badge_kills = 0;
434  for (i = 0; i < Num_medals; i++)
435  {
436  if (Medals[i].kills_needed < prev_badge_kills && Medals[i].kills_needed != 0)
437  Error(LOCATION, "Badges must appear sorted by lowest kill # first in medals.tbl\nFind Allender for most information.");
438 
439  if (Medals[i].kills_needed > 0)
440  prev_badge_kills = Medals[i].kills_needed;
441  }
442  }
443  catch (const parse::ParseException& e)
444  {
445  mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", "medals.tbl", e.what()));
446  return;
447  }
448 }
449 
450 // replacement for -gimmemedals
451 DCF(medals, "Grant or revoke medals")
452 {
453  int i;
454  int idx;
455 
456  if (dc_optional_string_either("help", "--help"))
457  {
458  dc_printf ("Usage: medals all | clear | promote | demote | [index]\n");
459  dc_printf (" [index] -- index of medal to grant\n");
460  dc_printf (" with no parameters, displays the available medals\n");
461  return;
462  }
463 
464  if (dc_optional_string_either("status", "--status") || dc_optional_string_either("?", "--?"))
465  {
466  dc_printf("You have the following medals:\n");
467 
468  for (i = 0; i < Num_medals; i++)
469  {
470  if (Player->stats.medal_counts[i] > 0)
471  dc_printf("%d %s\n", Player->stats.medal_counts[i], Medals[i].name);
472  }
473  dc_printf("%s\n", Ranks[Player->stats.rank].name);
474  return;
475  }
476 
477  if (dc_optional_string("all")) {
478  for (i = 0; i < Num_medals; i++) {
480  }
481  dc_printf("Granted all medals\n");
482  return;
483 
484  } else if (dc_optional_string("clear")) {
485  for (i = 0; i < Num_medals; i++) {
486  Player->stats.medal_counts[i] = 0;
487  }
488  dc_printf("Cleared all medals\n");
489  return;
490 
491  } else if (dc_optional_string("promote")) {
493  Player->stats.rank++;
494  }
495  dc_printf("Promoted to %s\n", Ranks[Player->stats.rank].name);
496  return;
497 
498  } else if (dc_optional_string("demote")) {
499  if (Player->stats.rank > 0) {
500  Player->stats.rank--;
501  }
502  dc_printf("Demoted to %s\n", Ranks[Player->stats.rank].name);
503  return;
504  }
505 
506  if (dc_maybe_stuff_int(&idx)) {
507  if (idx < 0 || idx >= Num_medals)
508  {
509  dc_printf("Medal index %d is out of range\n", idx);
510  return;
511  }
512 
513  dc_printf("Granted %s\n", Medals[idx].name);
515  return;
516  }
517 
518  dc_printf("The following medals are available:\n");
519  for (i = 0; i < Num_medals; i++) {
520  dc_printf("%d: %s\n", i, Medals[i].name);
521  }
522 }
523 
524 
526 {
527  int idx;
528  char bitmap_buf[NAME_LENGTH];
529 
530  Assert(pl != NULL);
531  Medals_player = pl;
532  Player_score = &Medals_player->stats;
533 
534 #ifndef NDEBUG
536  for (idx=0; idx < Num_medals; idx++){
537  Medals_player->stats.medal_counts[idx] = 1;
538  }
539  }
540 #endif
541 
542  for (idx=0; idx < Num_medals; idx++) {
543  if ((Medals[idx].available_from_start) && (Medals_player->stats.medal_counts[idx] < 1)) {
544  Medals_player->stats.medal_counts[idx] = 1;
545  }
546  }
547 
548  Medals_mode = mode;
550  Medals_window.create( 0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0 );
551 
552  // create the interface buttons
553  for (idx=0; idx<MEDALS_NUM_BUTTONS; idx++) {
554  // create the object
555  Medals_buttons[gr_screen.res][idx].button.create(&Medals_window, "", Medals_buttons[gr_screen.res][idx].x, Medals_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
556 
557  // set the sound to play when highlighted
559 
560  // set the ani for the button
561  Medals_buttons[gr_screen.res][idx].button.set_bmaps(Medals_buttons[gr_screen.res][idx].filename);
562 
563  // set the hotspot
564  Medals_buttons[gr_screen.res][idx].button.link_hotspot(Medals_buttons[gr_screen.res][idx].hotspot);
565  }
566 
567  // add all xstrs
568  for (idx=0; idx<MEDALS_NUM_TEXT; idx++) {
569  Medals_window.add_XSTR(&Medals_text[gr_screen.res][idx]);
570  }
571 
572  Init_flags = 0;
573 
575  strcat_s(bitmap_buf, Medals_background_filename);
576 
577  Medals_bitmap = bm_load(bitmap_buf);
578  if (Medals_bitmap < 0) {
579  Error(LOCATION, "Error loading medal background bitmap %s", bitmap_buf);
580  } else {
582  }
583 
584  Medals_mask_w = -1;
585  Medals_mask_h = -1;
586 
588  strcat_s(bitmap_buf, Medals_mask_filename);
589 
590  Medals_bitmap_mask = bm_load(bitmap_buf);
591  if (Medals_bitmap_mask < 0) {
592  Error(LOCATION, "Error loading medal mask file %s", bitmap_buf);
593  } else {
595  Medals_mask = bm_lock(Medals_bitmap_mask, 8, BMP_AABITMAP);
596  bm_get_info(Medals_bitmap_mask, &Medals_mask_w, &Medals_mask_h);
597  }
600 
602 
603  Medals_window.set_mask_bmap(bitmap_buf);
604 }
605 
606 void blit_label(char *label, int num)
607 {
608  int x, y, sw;
609  char text[256];
610 
612 
613  // translate medal names before displaying
614  // can't translate in table cuz the names are used in comparisons
615  if (Lcl_gr) {
616  char translated_label[256];
617  strcpy_s(translated_label, label);
618  lcl_translate_medal_name_gr(translated_label);
619 
620  // set correct string
621  if ( num > 1 ) {
622  sprintf( text, NOX("%s (%d)"), translated_label, num );
623  } else {
624  sprintf( text, "%s", translated_label );
625  }
626  } else if (Lcl_pl) {
627  char translated_label[256];
628  strcpy_s(translated_label, label);
629  lcl_translate_medal_name_pl(translated_label);
630 
631  // set correct string
632  if ( num > 1 ) {
633  sprintf( text, NOX("%s (%d)"), translated_label, num );
634  } else {
635  sprintf( text, "%s", translated_label );
636  }
637  } else {
638  // set correct string
639  if ( num > 1 ) {
640  sprintf( text, NOX("%s (%d)"), label, num );
641  } else {
642  sprintf( text, "%s", label );
643  }
644  }
645 
646  // find correct coords
647  gr_get_string_size(&sw, NULL, text);
648  x = Medals_label_coords[gr_screen.res].x + (Medals_label_coords[gr_screen.res].w - sw) / 2;
649  y = Medals_label_coords[gr_screen.res].y;
650 
651  // do it
652  gr_string(x, y, text, GR_RESIZE_MENU);
653 }
654 
656 {
657  int x, y;
658 
660 
661  // find correct coords
662  x = Medals_callsign_coords[gr_screen.res].x;
663  y = Medals_callsign_coords[gr_screen.res].y;
664 
665  // nothing special, just do it.
666  // Goober5000 - from previous code revisions, I assume 0x8000 means center it on-screen...
667  gr_string((x < 0) ? 0x8000 : x, y, Medals_player->callsign, GR_RESIZE_MENU);
668 }
669 
671 {
672  int region,selected, k;
673  k = Medals_window.process();
674 
675  // process an exit command
676  if ( (k == KEY_ESC) && (Medals_mode == MM_NORMAL) ) {
678  }
679 
680  // draw the background medal display case
681  gr_reset_clip();
682  GR_MAYBE_CLEAR_RES(Medals_bitmap);
683  if (Medals_bitmap != -1) {
684  gr_set_bitmap(Medals_bitmap);
686  }
687 
688  // check to see if a button was pressed
689  if ( (k == (KEY_CTRLED|KEY_ENTER)) || (Medals_buttons[gr_screen.res][MEDALS_EXIT].button.pressed()) ) {
691  if (Medals_mode == MM_NORMAL) {
693  } else {
694  // any calling popup function will know to close the screen down
695  return 0;
696  }
697  }
698 
699  // blit medals also takes care of blitting the rank insignia
700  blit_medals();
701  blit_callsign();
702 
703  region = snazzy_menu_do((ubyte*)Medals_mask->data, Medals_mask_w, Medals_mask_h, Num_medals, Medal_regions, &selected);
704  if (region == Rank_medal_index)
705  {
706  blit_label(Ranks[Player_score->rank].name, 1);
707  }
708  else switch (region)
709  {
710  case ESC_PRESSED:
711  if (Medals_mode == MM_NORMAL) {
713  } else {
714  // any calling popup function will know to close the screen down
715  return 0;
716  }
717  break;
718 
719  case -1:
720  break;
721 
722  default:
723  if (Player_score->medal_counts[region] > 0) {
724  blit_label(Medals[region].name, Player_score->medal_counts[region]);
725  }
726  break;
727  } // end switch
728 
729  Medals_window.draw();
730 
731  gr_flip();
732 
733  return 1;
734 }
735 
737 {
739  bm_release(Medals_bitmap);
740 
742  bm_unlock(Medals_bitmap_mask);
743  bm_release(Medals_bitmap_mask);
744  }
745 
746  for (SCP_vector<medal_display_info>::iterator idx = Medal_display_info.begin(); idx != Medal_display_info.end(); ++idx) {
747  if (idx->bitmap >= 0){
748  bm_release(idx->bitmap);
749  }
750  idx->bitmap = -1;
751  }
752 
753  delete[] Medal_regions;
754  Medal_regions = NULL;
755 
756  Player_score = NULL;
757  Medals_window.destroy();
760 }
761 
762 // function to load in the medals for this player. It loads medals that the player has (known
763 // by whether or not a non-zero number is present in the player's medal array), then loads the
764 // rank bitmap
766 {
767  int idx;
768  Assert(Player_score);
769 
770  for (idx=0; idx<Num_medals; idx++) {
771  Medal_display_info[idx].bitmap = -1;
772 
773  if (Player_score->medal_counts[idx] > 0) {
774  int num_medals;
776 
777  // possibly load a different filename that is specified by the bitmap filename
778  // for this medal. if the player has > 1 of these types of medals, then determien
779  // which of the possible version to use based on the player's count of this medal
780  strcpy_s( filename, Medals[idx].bitmap );
781 
782  _splitpath( filename, NULL, NULL, base, NULL );
783 
784  num_medals = Player_score->medal_counts[idx];
785 
786  // can't display more than the maximum number of version for this medal
787  if ( num_medals > Medals[idx].num_versions )
788  num_medals = Medals[idx].num_versions;
789 
790  if ( num_medals > 1 ) {
791  // append the proper character onto the end of the medal filename. Base version
792  // has no character. next version is a, then b, etc.
793  char temp[MAX_FILENAME_LEN];
794  strcpy_s(temp, base);
795  sprintf( base, "%s%c", temp, (num_medals-2)+'a');
796  }
797 
798  // hi-res support
799  if (gr_screen.res == GR_1024) {
800  sprintf( filename, "2_%s", base );
801  }
802 
803  // base now contains the actual medal bitmap filename needed to load
804  // we don't need to pass extension to bm_load anymore, so just use the basename
805  // as is.
806  Medal_display_info[idx].bitmap = bm_load((gr_screen.res == GR_1024) ? filename : base);
807  Assert( Medal_display_info[idx].bitmap != -1 );
808  }
809  }
810 
811  // load up rank insignia
812  if (gr_screen.res == GR_1024) {
813  char filename[NAME_LENGTH];
814  sprintf(filename, "2_%s", Ranks[Player_score->rank].bitmap);
815  Rank_bm = bm_load(filename);
816  } else {
817  Rank_bm = bm_load(Ranks[Player_score->rank].bitmap);
818  }
819 }
820 
822 {
823  int idx;
824 
825  // well, we need regions in an array (versus a vector), so...
826  Assert(Medal_regions == NULL);
827  Medal_regions = new MENU_REGION[Num_medals];
828 
829  // snazzy regions for the medals/ranks, etc.
830  for (idx=0; idx<Num_medals; idx++) {
831  snazzy_menu_add_region(&Medal_regions[idx], "", idx, 0);
832  }
833 }
834 
835 // blit the medals -- this includes the rank insignia
837 {
838  int idx;
839 
840  for (idx=0; idx<Num_medals; idx++) {
841  if (idx != Rank_medal_index && Player_score->medal_counts[idx] > 0) {
842 #ifndef NDEBUG
843  // this can happen if gimmemedals was used on the medal screen
844  if (Medal_display_info[idx].bitmap < 0) {
845  continue;
846  }
847 #endif
848  gr_set_bitmap(Medal_display_info[idx].bitmap);
849  gr_bitmap(Medal_display_info[idx].coords[gr_screen.res].x, Medal_display_info[idx].coords[gr_screen.res].y, GR_RESIZE_MENU);
850  }
851  }
852 
853  // now blit rank, since that "medal" doesn't get loaded (or drawn) the normal way
854  gr_set_bitmap(Rank_bm);
855  gr_bitmap(Medal_display_info[Rank_medal_index].coords[gr_screen.res].x, Medal_display_info[Rank_medal_index].coords[gr_screen.res].y, GR_RESIZE_MENU);
856 }
857 
858 int medals_info_lookup(const char *name)
859 {
860  if ( !name ) {
861  return -1;
862  }
863 
864  for (int i = 0; i < Num_medals; i++) {
865  if ( !stricmp(name, Medals[i].name) ) {
866  return i;
867  }
868  }
869 
870  return -1;
871 }
void bm_unlock(int handle)
Unlocks a bitmap.
Definition: bmpman.cpp:3005
char name[NAME_LENGTH]
Definition: medals.h:31
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
void set_highlight_action(void(*_user_function)(void))
Definition: button.cpp:375
void medal_main_close()
Definition: medals.cpp:736
int i
Definition: multi_pxo.cpp:466
SCP_vector< medal_stuff > Medals
Definition: medals.cpp:33
#define vm_free(ptr)
Definition: pstypes.h:548
scoring_struct * Player_score
Definition: medals.cpp:148
void add_XSTR(char *string, int _xstr_id, int _x, int _y, UI_GADGET *_assoc, int _color_type, int _font_id=-1)
Definition: window.cpp:476
int Medals_mask_w
Definition: medals.cpp:162
int check_for_string(const char *pstr)
Definition: parselo.cpp:517
void gr_flip()
Definition: 2d.cpp:2113
commit pressed
Definition: gamesnd.h:294
int x
Definition: ui.h:658
#define GR_RESIZE_MENU
Definition: 2d.h:684
int y
Definition: ui.h:658
void lcl_translate_medal_name_gr(char *name)
Definition: localize.cpp:1502
int num_versions
Definition: medals.h:34
int medals_info_lookup(const char *name)
Definition: medals.cpp:858
int snazzy_menu_do(ubyte *data, int mask_w, int mask_h, int num_regions, MENU_REGION *regions, int *action, int poll_key, int *key)
Definition: snazzyui.cpp:59
int Rank_medal_index
Definition: medals.cpp:177
#define MEDALS_NUM_TEXT
Definition: medals.cpp:132
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
bool dc_maybe_stuff_int(int *i)
Tries to stuff an int from the Command_string.
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
#define mprintf(args)
Definition: pstypes.h:238
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
struct medal_display_info medal_display_info
int medal_main_do()
Definition: medals.cpp:670
int res
Definition: 2d.h:370
int y
Definition: medals.cpp:104
int max_h_unscaled
Definition: 2d.h:361
int bm_get_info(int handle, int *w, int *h, ubyte *flags, int *nframes, int *fps)
Gets info on the bitmap indexed by handle.
Definition: bmpman.cpp:769
int Lcl_pl
Definition: localize.cpp:49
char voice_base[MAX_FILENAME_LEN]
Definition: medals.h:40
char debrief_bitmap[MAX_FILENAME_LEN]
Definition: medals.h:33
#define ESC_PRESSED
Definition: snazzyui.h:16
#define GR_MAYBE_CLEAR_RES(bmap)
Definition: 2d.h:639
GLenum mode
Definition: Glext.h:5794
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
int x
Definition: pstypes.h:218
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
int max_w_unscaled
Definition: 2d.h:361
int required_string_either(char *str1, char *str2)
Checks for one of two required strings.
Definition: parselo.cpp:673
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
DCF(medals,"Grant or revoke medals")
Definition: medals.cpp:451
int bm_release(int handle, int clear_render_targets)
Frees both a bitmap's data and it's associated slot.
Definition: bmpman.cpp:2603
void snazzy_menu_add_region(MENU_REGION *region, const char *text, int mask, int key, int click_sound)
Definition: snazzyui.cpp:163
char callsign[CALLSIGN_LEN+1]
Definition: player.h:91
#define MEDAL_BITMAP_INIT
Definition: medals.cpp:180
void parse_medal_tbl()
Definition: medals.cpp:246
int y
Definition: pstypes.h:218
#define BMP_AABITMAP
antialiased bitmap
Definition: bmpman.h:52
void destroy()
Definition: window.cpp:189
#define gr_reset_clip
Definition: 2d.h:745
const medal_stuff & operator=(const medal_stuff &m)
Definition: medals.cpp:230
void set_mask_bmap(char *fname)
Definition: window.cpp:75
int set_bmaps(char *ani_filename, int nframes=3, int start_frame=1)
Definition: gadget.cpp:71
Definition: player.h:85
void medal_main_init(player *pl, int mode)
Definition: medals.cpp:525
color Color_bright
Definition: alphacolors.cpp:28
#define MM_NORMAL
Definition: medals.h:58
GLuint coords
Definition: Glext.h:6925
void snazzy_menu_close()
Definition: snazzyui.cpp:276
#define MULTITEXT_LENGTH
Definition: globals.h:21
coord2d coords[GR_NUM_RESOLUTIONS]
Definition: medals.cpp:171
#define MEDALS_NUM_BUTTONS
Definition: medals.cpp:121
char * filename
int hotspot
Definition: ui.h:659
int pressed()
Definition: button.cpp:325
bool available_from_start
Definition: medals.h:36
void stuff_string(char *outstr, int type, int len, char *terminators)
Definition: parselo.cpp:1189
int Cmdline_gimme_all_medals
Definition: cmdline.cpp:273
#define CF_TYPE_TABLES
Definition: cfile.h:50
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define KEY_ENTER
Definition: key.h:125
#define MASK_BITMAP_INIT
Definition: medals.cpp:181
#define GR_640
Definition: 2d.h:652
#define vm_strdup(ptr)
Definition: pstypes.h:549
int required_string(const char *pstr)
Definition: parselo.cpp:468
Definition: bmpman.h:101
bitmap * bm_lock(int handle, ubyte bpp, ubyte flags, bool nodebug)
Locks down the bitmap indexed by bitmapnum.
Definition: bmpman.cpp:1754
int optional_string(const char *pstr)
Definition: parselo.cpp:539
SCP_vector< int > medal_counts
Definition: scoring.h:85
int Medals_mode
Definition: medals.cpp:150
bool dc_optional_string_either(const char *str1, const char *str2)
Searches for an optional string and it's alias.
UI_BUTTON button
Definition: ui.h:660
void snazzy_menu_init()
Definition: snazzyui.cpp:34
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
Definition: parselo.cpp:1995
int idx
Definition: multiui.cpp:761
player * Medals_player
Definition: medals.cpp:151
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
unsigned char ubyte
Definition: pstypes.h:62
int Init_flags
Definition: medals.cpp:182
void stuff_boolean(int *i, bool a_to_eol)
Definition: parselo.cpp:2519
void _splitpath(char *path, char *drive, char *dir, char *fname, char *ext)
#define NOX(s)
Definition: pstypes.h:473
char bitmap[MAX_FILENAME_LEN]
Definition: medals.h:32
SCP_map< int, char * > promotion_text
Definition: medals.h:41
#define MEDALS_EXIT
Definition: medals.cpp:122
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
int x
Definition: medals.cpp:104
void reset_parse(char *text)
Definition: parselo.cpp:3305
GLuint const GLchar * name
Definition: Glext.h:5608
bool version_starts_at_1
Definition: medals.h:35
void init_medal_bitmaps()
Definition: medals.cpp:765
int kills_needed
Definition: medals.h:37
int bm_load(const char *real_filename)
Loads a bitmap so we can draw with it later.
Definition: bmpman.cpp:1119
void stuff_int(int *i)
Definition: parselo.cpp:2372
void blit_label(char *label, int num)
Definition: medals.cpp:606
~medal_stuff()
Definition: medals.cpp:193
GLuint GLuint num
Definition: Glext.h:9089
void blit_medals()
Definition: medals.cpp:836
void blit_callsign()
Definition: medals.cpp:655
#define NUM_MEDALS_FS2
Definition: scoring.h:24
void link_hotspot(int num)
Definition: gadget.cpp:50
#define strcat_s(...)
Definition: safe_strings.h:68
void create(UI_WINDOW *wnd, char *_text, int _x, int _y, int _w, int _h, int do_repeat=0, int ignore_focus=0)
Definition: button.cpp:26
#define KEY_ESC
Definition: key.h:124
#define NAME_LENGTH
Definition: globals.h:15
const char * label
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
const char * Resolution_prefixes[GR_NUM_RESOLUTIONS]
Definition: 2d.cpp:44
#define UI_XSTR_COLOR_PINK
Definition: ui.h:161
UI_XSTR Medals_text[GR_NUM_RESOLUTIONS][MEDALS_NUM_TEXT]
Definition: medals.cpp:133
void create(int _x, int _y, int _w, int _h, int _flags, int _f_id=-1)
Definition: window.cpp:140
player * Player
Definition: ui.h:584
screen gr_screen
Definition: 2d.cpp:46
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
Definition: ui.h:162
void palette_restore_palette()
Definition: palman.cpp:588
#define F_NAME
Definition: parselo.h:34
An overhauled/updated debug console to allow monitoring, testing, and general debugging of new featur...
#define LOCATION
Definition: pstypes.h:245
void common_play_highlight_sound()
Definition: gamesnd.cpp:1151
void init_snazzy_regions()
Definition: medals.cpp:821
ptr_u data
Pointer to data, or maybe offset into VRAM.
Definition: bmpman.h:109
const GLfloat * m
Definition: Glext.h:10319
#define KEY_CTRLED
Definition: key.h:64
int w
Definition: medals.cpp:104
color Color_normal
Definition: alphacolors.cpp:28
char * filename
Definition: ui.h:657
rank_stuff Ranks[NUM_RANKS]
Definition: scoring.cpp:45
void gr_bitmap(int _x, int _y, int resize_mode)
Definition: 2d.cpp:1303
bool dc_optional_string(const char *pstr)
Searches for an optional string.
int temp
Definition: lua.cpp:4996
void dc_printf(const char *format,...)
Prints the given char string to the debug console.
Definition: console.cpp:358
false
Definition: lua.cpp:6789
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
void draw()
Definition: window.cpp:220
struct ui_button_info ui_button_info
#define MAX_FREESPACE2_RANK
Definition: scoring.h:42
int process(int key_in=-1, int process_mouse=1)
Definition: window.cpp:401
int Num_medals
Definition: medals.cpp:30
void gameseq_post_event(int event)
void lcl_translate_medal_name_pl(char *name)
Definition: localize.cpp:1563
#define F_MULTITEXT
Definition: parselo.h:43
ui_button_info Medals_buttons[GR_NUM_RESOLUTIONS][MEDALS_NUM_BUTTONS]
Definition: medals.cpp:123
#define stricmp(s1, s2)
Definition: config.h:271
char bitmap[MAX_FILENAME_LEN]
Definition: scoring.h:69
#define GR_1024
Definition: 2d.h:653
int Lcl_gr
Definition: localize.cpp:48
struct coord2dw coord2dw
GLint y
Definition: Gl.h:1505
scoring_struct stats
Definition: player.h:127
#define strcpy_s(...)
Definition: safe_strings.h:67
char name[NAME_LENGTH]
Definition: scoring.h:66
int Medals_mask_h
Definition: medals.cpp:162