]> icculus.org git repositories - taylor/freespace2.git/blob - src/stats/medals.cpp
Initial revision
[taylor/freespace2.git] / src / stats / medals.cpp
1 /*
2  * $Logfile: /Freespace2/code/Stats/Medals.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  * 
7  * $Log$
8  * Revision 1.1  2002/05/03 03:28:11  root
9  * Initial revision
10  *
11  * 
12  * 12    10/29/99 10:40p Jefff
13  * hack to make german medal names display without actually changing them
14  * 
15  * 11    9/02/99 3:41p Jefff
16  * changed badge voice handling to be similar to promotion voice handling
17  * 
18  * 10    8/26/99 8:49p Jefff
19  * Updated medals screen and about everything that ever touches medals in
20  * one way or another.  Sheesh.
21  * 
22  * 9     7/16/99 1:50p Dave
23  * 8 bit aabitmaps. yay.
24  * 
25  * 8     3/19/99 9:51a Dave
26  * Checkin to repair massive source safe crash. Also added support for
27  * pof-style nebulae, and some new weapons code.
28  * 
29  * 8     3/15/99 10:29a Neilk
30  * 
31  * 7     1/30/99 5:08p Dave
32  * More new hi-res stuff.Support for nice D3D textures.
33  * 
34  * 6     12/18/98 1:13a Dave
35  * Rough 1024x768 support for Direct3D. Proper detection and usage through
36  * the launcher.
37  * 
38  * 5     11/30/98 1:07p Dave
39  * 16 bit conversion, first run.
40  * 
41  * 4     10/23/98 3:51p Dave
42  * Full support for tstrings.tbl and foreign languages. All that remains
43  * is to make it active in Fred.
44  * 
45  * 3     10/13/98 9:29a Dave
46  * Started neatening up freespace.h. Many variables renamed and
47  * reorganized. Added AlphaColors.[h,cpp]
48  * 
49  * 2     10/07/98 10:54a Dave
50  * Initial checkin.
51  * 
52  * 1     10/07/98 10:51a Dave
53  * 
54  * 26    6/13/98 3:18p Hoffoss
55  * NOX()ed out a bunch of strings that shouldn't be translated.
56  * 
57  * 25    6/01/98 11:43a John
58  * JAS & MK:  Classified all strings for localization.
59  * 
60  * 24    5/01/98 12:34p John
61  * Added code to force FreeSpace to run in the same dir as exe and made
62  * all the parse error messages a little nicer.
63  * 
64  * 23    4/27/98 3:13p Allender
65  * make ctrl-enter work on medals screen
66  * 
67  * 22    4/23/98 8:27p Allender
68  * basic support for cutscene playback.  Into movie code in place.  Tech
69  * room can view cutscenes stored in CDROM_dir variable
70  * 
71  * 21    4/12/98 8:30p Allender
72  * minor medal changes to show number of medals if > 1
73  * 
74  * 20    4/10/98 4:51p Hoffoss
75  * Made several changes related to tooltips.
76  * 
77  * 19    3/18/98 12:03p John
78  * Marked all the new strings as externalized or not.
79  * 
80  * 18    3/11/98 5:02p Dave
81  * Put in code to support new medals artwork. Assorted multiplayer bug
82  * fixes.
83  * 
84  * 17    3/07/98 5:44p Dave
85  * Finished player info popup. Ironed out a few todo bugs.
86  * 
87  * 16    3/05/98 5:11p Allender
88  * fix up medals screen (again).  Don't do state transition when viewing
89  * medals from debriefing screen.
90  * 
91  * 15    3/05/98 2:32p Hoffoss
92  * Renamed Rank_bitmap to Rank_bm so it isn't named the same as the
93  * variable in the debrief screen which confuses the debugger.
94  * 
95  * 14    2/22/98 2:48p John
96  * More String Externalization Classification
97  * 
98  * 13    2/09/98 5:21p Hoffoss
99  * Made exit from medals screen to previous screen (instead of assuming
100  * it's the barracks) work.
101  * 
102  * 12    1/27/98 4:23p Allender
103  * enhanced internal scoring mechanisms.
104  * 
105  * 11    11/12/97 4:40p Dave
106  * Put in multiplayer campaign support parsing, loading and saving. Made
107  * command-line variables better named. Changed some things on the initial
108  * pilot select screen.
109  * 
110  * 10    11/12/97 9:30a Dave
111  * Fixed rank insignia tooltip not showing up.
112  * 
113  * 9     11/06/97 4:39p Allender
114  * a ton of medal work.  Removed an uneeded elemen in the scoring
115  * structure.  Fix up medals screen to apprioriate display medals (after
116  * mask was changed).  Fix Fred to only display medals which may actually
117  * be granted.  Added image_filename to player struct for Jason Hoffoss
118  * 
119  * 8     11/05/97 4:43p Allender
120  * reworked medal/rank system to read all data from tables.  Made Fred
121  * read medals.tbl.  Changed ai-warp to ai-warp-out which doesn't require
122  * waypoint for activation
123  *
124  * $NoKeywords: $
125  */
126
127
128 #include "medals.h"
129 #include "2d.h"
130 #include "snazzyui.h"
131 #include "bmpman.h"
132 #include "gamesequence.h"
133 #include "animplay.h"
134 #include "mouse.h"
135 #include "freespace.h"
136 #include "scoring.h"
137 #include "player.h"
138 #include "palman.h"
139 #include "ui.h"
140 #include "key.h"
141 #include "cmdline.h"
142 #include "gamesnd.h"
143 #include "alphacolors.h"
144 #include "localize.h"
145
146 //#define MAX_MEDAL_TYPES 63 // the # of medals which exist so far
147
148 /*
149 #define CALLSIGN_X 198
150 #define CALLSIGN_Y 80
151 #define CALLSIGN_W (439-CALLSIGN_X)
152 #define CALLSIGN_H (116-CALLSIGN_Y)
153 */
154
155 // define for the medal information
156 medal_stuff Medals[NUM_MEDALS];
157 badge_stuff Badge_info[MAX_BADGES];
158
159 // holds indices into Medals array of the badges for # kills
160 int Badge_index[MAX_BADGES];
161
162 // the rank section of the screen
163 #define RANK_MEDAL_REGION               12                      // region number of the rank medal
164
165 // coords for indiv medal bitmaps
166 int Medal_coords[GR_NUM_RESOLUTIONS][NUM_MEDALS][2] = {
167         {                               // GR_640
168                 { 89, 47 },                                     // eps. peg. lib
169                 { 486, 47 },                            // imp. order o' vasuda
170                 { 129, 130 },                           // dist flying cross
171                 { 208, 132 },                           // soc service
172                 { 361, 131 },                           // dist intel cross
173                 { 439, 130 },                           // order of galatea
174                 { 64, 234 },                            // meritorious unit comm.
175                 { 153, 234 },                           // medal of valor
176                 { 239, 241 },                           // gtva leg of honor
177                 { 326, 240 },                           // allied defense citation
178                 { 411, 234 },                           // neb campaign victory
179                 { 494, 234 },                           // ntf campaign victory
180                 { 189, 80 },                            // rank
181                 { 283, 91 },                            // wings
182                 { 372, 76 },                            // bronze kills badge
183                 { 403, 76 },                            // silver kills badge
184                 { 435, 76 },                            // gold kills badge
185                 { 300, 152 },                           // SOC unit crest
186         },
187         {                               // GR_1024
188                 { 143, 75 },                            // eps. peg. lib
189                 { 777, 75 },                            // imp. order o' vasuda
190                 { 206, 208 },                           // dist flying cross
191                 { 333, 212 },                           // soc service
192                 { 578, 210 },                           // dist intel cross
193                 { 703, 208 },                           // order of galatea
194                 { 103, 374 },                           // meritorious unit comm.
195                 { 245, 374 },                           // medal of valor
196                 { 383, 386 },                           // gtva leg of honor
197                 { 522, 384 },                           // allied defense citation
198                 { 658, 374 },                           // neb campaign victory
199                 { 790, 374 },                           // ntf campaign victory
200                 { 302, 128 },                           // rank
201                 { 453, 146 },                           // wings
202                 { 595, 121 },                           // bronze kills badge
203                 { 646, 121 },                           // silver kills badge
204                 { 696, 121 },                           // gold kills badge
205                 { 480, 244 },                           // SOC unit crest
206         }
207 };
208
209 // coords for the medal title
210 static int Medals_label_coords[GR_NUM_RESOLUTIONS][3] = {
211         { 241, 458, 300 },                      // GR_640 x, y, w
212         { 386, 734, 480 }                               // GR_1024 x, y, w
213 };
214
215 #define MEDALS_NUM_BUTTONS                      1
216 #define MEDALS_EXIT                                     0       
217 ui_button_info Medals_buttons[GR_NUM_RESOLUTIONS][MEDALS_NUM_BUTTONS] = {
218         { // GR_640
219                 ui_button_info("MEB_18",        574,    432,    -1,     -1,     18),
220         },
221         { // GR_1024
222                 ui_button_info("2_MEB_18",      919,    691,    -1,     -1,     18),
223         }
224 };
225
226 #define MEDALS_NUM_TEXT                         1
227 UI_XSTR Medals_text[GR_NUM_RESOLUTIONS][MEDALS_NUM_TEXT] = {
228         {       // GR_640
229                 {"Exit",                1466,           587,    416,    UI_XSTR_COLOR_PINK, -1, &Medals_buttons[GR_640][MEDALS_EXIT].button },
230         },
231         {       // GR_1024
232                 {"Exit",                1466,           943,    673,    UI_XSTR_COLOR_PINK, -1, &Medals_buttons[GR_1024][MEDALS_EXIT].button },
233         },
234 };
235
236 static char* Medals_background_filename[GR_NUM_RESOLUTIONS] = {
237         "MedalsDisplayEmpty",
238         "2_MedalsDisplayEmpty"
239 };
240
241 static char* Medals_mask_filename[GR_NUM_RESOLUTIONS] = {
242         "Medals-m",
243         "2_Medals-m"
244 };
245
246 static int Medals_callsign_y[GR_NUM_RESOLUTIONS] = {
247         54, 89
248 };
249
250 scoring_struct *Player_score=NULL;
251
252 int Medals_mode;
253 player *Medals_player;
254
255 // -----------------------------------------------------------------------------
256 // Main medals screen state
257 //
258 #define NUM_MEDAL_REGIONS                       NUM_MEDALS + 1                          // the extra one is for the rank medal
259
260 static bitmap *Medals_mask;
261 int Medals_mask_w, Medals_mask_h;
262 static int Medal_palette;              // Medal palette bitmap
263 static int Medals_bitmap_mask;         // the mask for the medal case
264 static int Medals_bitmap;              // the medal case itself
265 static int Medal_bitmaps[NUM_MEDALS];  // bitmaps for the individual medals
266 static int Rank_bm;                                                     // bitmap for the rank medal
267
268 static MENU_REGION Medal_regions[NUM_MEDAL_REGIONS]; // a semi-hack for now because we only have 4 medals, but we also include the close button
269
270 static UI_WINDOW Medals_window;
271
272 //#define MAX_MEDALS_BUTTONS                                            1
273 //#define MEDAL_BUTTON_EXIT                                             0
274 //static UI_BUTTON Medal_buttons[MAX_MEDALS_BUTTONS];
275
276 /*static char *Medal_button_names[MAX_MEDALS_BUTTONS] = {
277 //XSTR:OFF
278         "MX_17"
279 //XSTR:ON
280 };
281 */
282 /*
283 static int Medal_button_coords[MAX_MEDALS_BUTTONS][2] = {
284         {561,411}
285 };
286 static int Medal_button_masks[MAX_MEDALS_BUTTONS] = {
287         17
288 };
289 */
290
291
292 #define MEDAL_BITMAP_INIT (1<<0)
293 #define MASK_BITMAP_INIT  (1<<1)
294 int Init_flags;
295
296 void parse_medal_tbl()
297 {
298         int rval, num_medals, i, bi;
299
300         if ((rval = setjmp(parse_abort)) != 0) {
301                 Error(LOCATION, "Error parsing 'medals.tbl'\r\nError code = %i.\r\n", rval);
302         } 
303
304         // open localization
305         lcl_ext_open();
306
307         read_file_text("medals.tbl");
308
309         reset_parse();
310
311         // parse in all the rank names
312         num_medals = 0;
313         bi = 0;
314         required_string("#Medals");
315         while ( required_string_either("#End", "$Name:") ) {
316                 Assert ( num_medals < NUM_MEDALS);
317                 required_string("$Name:");
318                 stuff_string( Medals[num_medals].name, F_NAME, NULL );
319                 required_string("$Bitmap:");
320                 stuff_string( Medals[num_medals].bitmap, F_NAME, NULL );
321                 required_string("$Num mods:");
322                 stuff_int( &Medals[num_medals].num_versions);
323
324                 // some medals are based on kill counts.  When string +Num Kills: is present, we know that
325                 // this medal is a badge and should be treated specially
326                 Medals[num_medals].kills_needed = 0;
327                 if ( optional_string("+Num Kills:") ) {
328                         char buf[MULTITEXT_LENGTH + 1];
329
330                         Assert( bi < MAX_BADGES );
331                         stuff_int( &Medals[num_medals].kills_needed );
332                         Badge_index[bi] = num_medals;
333
334                         required_string("$Wavefile Base:");
335                         stuff_string(Badge_info[bi].voice_base, F_NAME, NULL, MAX_FILENAME_LEN);
336
337                         //required_string("$Wavefile 2:");
338                         //stuff_string(Badge_info[bi].wave2, F_NAME, NULL, MAX_FILENAME_LEN);
339
340                         required_string("$Promotion Text:");
341                         stuff_string(buf, F_MULTITEXT, NULL);
342                         Badge_info[bi].promotion_text = strdup(buf);
343
344                         bi++;
345                 }
346
347                 num_medals++;
348         }
349
350         required_string("#End");
351         Assert( num_medals == NUM_MEDALS );
352
353         // be sure that the badges kill numbers show up in order
354         for (i = 0; i < MAX_BADGES-1; i++ ) {
355                 if ( Medals[Badge_index[i]].kills_needed >= Medals[Badge_index[i+1]].kills_needed ){
356                         Error(LOCATION, "Badges must appear sorted by lowest kill # first in medals.tbl\nFind Allender for most information.");
357                 }
358         }
359
360         // close localization
361         lcl_ext_close();
362 }
363
364 void medal_main_init(player *pl, int mode)
365 {
366         int idx;
367
368         Assert(pl != NULL);
369         Medals_player = pl;
370
371    Player_score = &Medals_player->stats;
372
373         #ifndef NDEBUG
374         if(Cmdline_gimme_all_medals){
375                 //int idx;
376                 for(idx=0; idx < NUM_MEDALS; idx++){
377                         Medals_player->stats.medals[idx] = 1;           
378                 }
379         }
380         #endif
381
382         Medals_mode = mode;
383
384         snazzy_menu_init();
385         Medals_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );      
386
387         // create the interface buttons
388         for (idx=0; idx<MEDALS_NUM_BUTTONS; idx++) {
389                 // create the object
390                 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);
391
392                 // set the sound to play when highlighted
393                 Medals_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
394
395                 // set the ani for the button
396                 Medals_buttons[gr_screen.res][idx].button.set_bmaps(Medals_buttons[gr_screen.res][idx].filename);
397
398                 // set the hotspot
399                 Medals_buttons[gr_screen.res][idx].button.link_hotspot(Medals_buttons[gr_screen.res][idx].hotspot);
400         }       
401
402         // add all xstrs
403         for (idx=0; idx<MEDALS_NUM_TEXT; idx++) {
404                 Medals_window.add_XSTR(&Medals_text[gr_screen.res][idx]);
405         }
406
407
408         Init_flags = 0; 
409
410         //init_medal_palette();
411         
412         Medals_bitmap = bm_load(Medals_background_filename[gr_screen.res]);
413         if (Medals_bitmap < 0) {
414            Error(LOCATION, "Error loading medal background bitmap %s", Medals_background_filename[gr_screen.res]);
415         } else {
416                 Init_flags |= MEDAL_BITMAP_INIT;
417         }
418
419         Medals_mask_w = -1;
420         Medals_mask_h = -1;
421       
422         Medals_bitmap_mask = bm_load(Medals_mask_filename[gr_screen.res]);
423         if(Medals_bitmap_mask < 0){
424                 Error(LOCATION, "Error loading medal mask file %s", Medals_mask_filename[gr_screen.res]);
425         } else {
426                 Init_flags |= MASK_BITMAP_INIT;
427                 Medals_mask = bm_lock(Medals_bitmap_mask, 8, BMP_AABITMAP);
428                 bm_get_info(Medals_bitmap_mask, &Medals_mask_w, &Medals_mask_h);
429         }
430         init_medal_bitmaps();
431         init_snazzy_regions();
432
433         gr_set_color_fast(&Color_normal);
434
435         Medals_window.set_mask_bmap(Medals_mask_filename[gr_screen.res]);
436 }
437
438 // this is just a hack to display translated names without actually changing the names, 
439 // which would break stuff
440 void medals_translate_name(char *name, int max_len)
441 {
442         if (!strcmp(name, "Epsilon Pegasi Liberation")) {
443                 strncpy(name, "Epsilon Pegasi Befreiungsmedaille", max_len);
444
445         } else if (!strcmp(name, "Imperial Order of Vasuda")) {
446                 strncpy(name, "Imperialer Orden von Vasuda ", max_len);
447
448         } else if (!strcmp(name, "Distinguished Flying Cross")) {
449                 strncpy(name, "Fliegerkreuz Erster Klasse", max_len);
450
451         } else if (!strcmp(name, "SOC Service Medallion")) {
452                 strncpy(name, "SEK-Dienstmedaille ", max_len);
453
454         } else if (!strcmp(name, "Intelligence Cross")) {
455                 strncpy(name, "Geheimdienstkreuz am Bande", max_len);
456
457         } else if (!strcmp(name, "Order of Galatea")) {
458                 strncpy(name, "Orden von Galatea ", max_len);
459
460         } else if (!strcmp(name, "Meritorious Unit Commendation")) {
461                 strncpy(name, "Ehrenspange der Allianz", max_len);
462
463         } else if (!strcmp(name, "Medal of Valor")) {
464                 strncpy(name, "Tapferkeitsmedaille ", max_len);
465
466         } else if (!strcmp(name, "GTVA Legion of Honor")) {
467                 strncpy(name, "Orden der GTVA-Ehrenlegion", max_len);
468
469         } else if (!strcmp(name, "Allied Defense Citation")) {
470                 strncpy(name, "Alliierte Abwehrspange ", max_len);
471
472         } else if (!strcmp(name, "Nebula Campaign Victory Star")) {
473                 strncpy(name, "Nebel-Siegesstern", max_len);
474
475         } else if (!strcmp(name, "NTF Campaign Victory Star")) {
476                 strncpy(name, "NTF-Siegesstern ", max_len);
477
478         } else if (!strcmp(name, "Rank")) {
479                 strncpy(name, "Dienstgrad", max_len);
480
481         } else if (!strcmp(name, "Wings")) {
482                 strncpy(name, "Fliegerspange", max_len);
483
484         } else if (!strcmp(name, "Ace")) {
485                 strncpy(name, "Flieger-As", max_len);   
486
487         } else if (!strcmp(name, "Double Ace")) {
488                 strncpy(name, "Doppel-As ", max_len);
489
490         } else if (!strcmp(name, "Triple Ace")) {
491                 strncpy(name, "Dreifach-As ", max_len);
492                 
493         } else if (!strcmp(name, "SOC Unit Crest")) {
494                 strncpy(name, "SEK-Abzeichen ", max_len);       
495         }
496 }
497
498 void blit_label(char *label, int *coords, int num)
499 {
500         int x, y, sw;
501         char text[256];
502
503         gr_set_color_fast(&Color_bright);
504
505         // translate medal names before displaying
506         // cant translate in table cuz the names are used in comparisons
507         if (Lcl_gr) {
508                 char translated_label[256];
509                 strncpy(translated_label, label, 256);
510                 medals_translate_name(translated_label, 256);
511
512                 // set correct string
513                 if ( num > 1 ) {
514                         sprintf( text, NOX("%s (%d)"), translated_label, num );
515                 } else {
516                         sprintf( text, "%s", translated_label );
517                 }               
518         } else {
519                 // set correct string
520                 if ( num > 1 ) {
521                         sprintf( text, NOX("%s (%d)"), label, num );
522                 } else {
523                         sprintf( text, "%s", label );
524                 }
525         }
526
527         // find correct coords
528         gr_get_string_size(&sw, NULL, text);
529         x = Medals_label_coords[gr_screen.res][0] + (Medals_label_coords[gr_screen.res][2] - sw) / 2;
530         y = Medals_label_coords[gr_screen.res][1];
531
532         // do it
533         gr_string(x, y, text);
534 }
535
536 void blit_callsign()
537 {
538         gr_set_color_fast(&Color_normal);
539
540         // nothing special, just do it.
541         gr_string(0x8000, Medals_callsign_y[gr_screen.res], Medals_player->callsign);
542 }
543
544 int medal_main_do()
545 {
546    int region,selected, k;
547
548         k = Medals_window.process();    
549
550         // process an exit command
551         if ((k == KEY_ESC) && (Medals_mode == MM_NORMAL)) {
552                 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
553         }
554
555         // draw the background medal display case
556         gr_reset_clip();
557         GR_MAYBE_CLEAR_RES(Medals_bitmap);
558         if(Medals_bitmap != -1){
559                 gr_set_bitmap(Medals_bitmap);
560                 gr_bitmap(0,0);
561         }
562
563         // check to see if a button was pressed
564         if( (k == (KEY_CTRLED|KEY_ENTER)) || (Medals_buttons[gr_screen.res][MEDALS_EXIT].button.pressed()) ) {  
565                 gamesnd_play_iface(SND_COMMIT_PRESSED);
566                 if(Medals_mode == MM_NORMAL){
567                         gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
568                 } else {
569                         // any calling popup function will know to close the screen down
570                         return 0;
571                 }               
572         }
573
574         // blit medals also takes care of blitting the rank insignia
575         blit_medals(); 
576         blit_callsign();        
577         
578         region = snazzy_menu_do((ubyte*)Medals_mask->data, Medals_mask_w, Medals_mask_h, NUM_MEDAL_REGIONS, Medal_regions, &selected);
579         switch (region) {
580                 case ESC_PRESSED:
581                         if (Medals_mode == MM_NORMAL) {
582                                 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
583                         } else {
584                                 // any calling popup function will know to close the screen down
585                                 return 0;
586                         }
587                         break;
588
589                 case RANK_MEDAL_REGION :
590                         blit_label(Ranks[Player_score->rank].name, &Medal_coords[gr_screen.res][region][0], 1);
591                         break;
592
593                 case -1:
594                         break;
595
596                 default :
597         if (Player_score->medals[region] > 0){
598                                 blit_label(Medals[region].name, &Medal_coords[gr_screen.res][region][0], Player_score->medals[region] );
599                         }
600                         break;
601         } // end switch
602
603         Medals_window.draw();
604
605         gr_flip();
606
607         return 1;
608 }
609
610 void medal_main_close()
611 {
612         int idx;
613         if (Init_flags & MEDAL_BITMAP_INIT)
614                 bm_unload(Medals_bitmap);
615
616         if (Init_flags & MASK_BITMAP_INIT) {
617                 bm_unlock(Medals_bitmap_mask);
618                 bm_unload(Medals_bitmap_mask);
619         }
620
621    for (idx=0; idx < NUM_MEDALS; idx++) {
622                 if (Medal_bitmaps[idx] > -1){
623                         bm_unload(Medal_bitmaps[idx]);
624                 }
625         }
626
627    Player_score = NULL;
628         Medals_window.destroy();
629         snazzy_menu_close();
630         palette_restore_palette();
631 }
632
633 /*
634 void init_medal_palette()
635 {
636         Medal_palette = bm_load("MedalsPalette.pcx");
637         if(Medal_palette > -1){
638 #ifndef HARDWARE_ONLY
639                 palette_use_bm_palette(Medal_palette);
640 #endif
641         }
642 }
643 */
644
645 // function to load in the medals for this player.  It loads medals that the player has (known
646 // by whether or not a non-zero number is present in the player's medal array), then loads the
647 // rank bitmap
648
649 void init_medal_bitmaps()
650 {
651         int idx;
652         Assert(Player_score);
653
654         for (idx=0; idx<NUM_MEDALS; idx++) {
655                 Medal_bitmaps[idx] = -1;
656                 if (Player_score->medals[idx] > 0) {
657                         int num_medals;
658                         char filename[NAME_LENGTH], base[NAME_LENGTH];
659                         
660                         // possibly load a different filename that is specified by the bitmap filename
661                         // for this medal.  if the player has > 1 of these types of medals, then determien
662                         // which of the possible version to use based on the player's count of this medal
663                         strcpy( filename, Medals[idx].bitmap );
664                         _splitpath( filename, NULL, NULL, base, NULL );
665
666                         num_medals = Player_score->medals[idx];
667
668                         // can't display more than the maximum number of version for this medal
669                         if ( num_medals > Medals[idx].num_versions )
670                                 num_medals = Medals[idx].num_versions;
671
672                         if ( num_medals > 1 ) {
673                                 // append the proper character onto the end of the medal filename.  Base version
674                                 // has no character. next version is a, then b, etc.
675                                 sprintf( base, "%s%c", base, (num_medals-2)+'a');
676                         }
677         
678                         // hi-res support
679                         if (gr_screen.res == GR_1024) {
680                                 sprintf( filename, "2_%s", base );
681                         }
682
683                         // base now contains the actual medal bitmap filename needed to load
684                         // we don't need to pass extension to bm_load anymore, so just use the basename
685                         // as is.
686          Medal_bitmaps[idx] = bm_load( filename );
687                         Assert( Medal_bitmaps[idx] != -1 );
688                 }
689         }
690
691         // load up rank insignia
692         if (gr_screen.res == GR_1024) {
693                 char filename[NAME_LENGTH];
694                 sprintf(filename, "2_%s", Ranks[Player_score->rank].bitmap);
695                 Rank_bm = bm_load(filename);
696         } else {
697                 Rank_bm = bm_load(Ranks[Player_score->rank].bitmap);
698         }
699 }
700
701 void init_snazzy_regions()
702 {
703         int idx;
704
705         // snazzy regions for the medals/ranks, etc.
706         for (idx=0; idx<NUM_MEDALS; idx++) {
707                 if (idx == RANK_MEDAL_REGION) 
708                         continue;
709
710                 snazzy_menu_add_region(&Medal_regions[idx], "", idx, 0);
711         }
712
713         // add the rank medal region
714         snazzy_menu_add_region(&Medal_regions[RANK_MEDAL_REGION], "", RANK_MEDAL_REGION,0);
715 }
716
717
718 // blit the medals -- this includes the rank insignia
719 void blit_medals()
720 {
721         int idx;
722
723         for (idx=0; idx<NUM_MEDALS; idx++) {
724                 if (Player_score->medals[idx] > 0) {
725                         gr_set_bitmap(Medal_bitmaps[idx]);
726                         gr_bitmap(Medal_coords[gr_screen.res][idx][0], Medal_coords[gr_screen.res][idx][1]);
727                 }
728         }
729
730         // now blit rank, since that "medal" doesnt get loaded (or drawn) the normal way
731         gr_set_bitmap(Rank_bm);
732         gr_bitmap(Medal_coords[gr_screen.res][RANK_MEDAL_REGION][0], Medal_coords[gr_screen.res][RANK_MEDAL_REGION][1]);
733 }
734