]> icculus.org git repositories - taylor/freespace2.git/blob - src/stats/medals.cpp
fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
[taylor/freespace2.git] / src / stats / medals.cpp
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Stats/Medals.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  * 
15  * $Log$
16  * Revision 1.12  2004/07/04 11:39:06  taylor
17  * fix missing debrief text, crash on exit, path separator's, warning fixes, no GR_SOFT
18  *
19  * Revision 1.11  2003/08/03 16:10:30  taylor
20  * cleanup; compile warning fixes
21  *
22  * Revision 1.10  2003/06/11 18:30:33  taylor
23  * plug memory leaks
24  *
25  * Revision 1.9  2003/06/03 04:00:40  taylor
26  * Polish language support (Janusz Dziemidowicz)
27  *
28  * Revision 1.8  2003/05/25 02:30:44  taylor
29  * Freespace 1 support
30  *
31  * Revision 1.7  2002/06/09 04:41:27  relnev
32  * added copyright header
33  *
34  * Revision 1.6  2002/06/09 03:16:05  relnev
35  * added _splitpath.
36  *
37  * removed unneeded asm, old sdl 2d setup.
38  *
39  * fixed crash caused by opengl_get_region.
40  *
41  * Revision 1.5  2002/05/28 08:52:03  relnev
42  * implemented two assembly stubs.
43  *
44  * cleaned up a few warnings.
45  *
46  * added a little demo hackery to make it progress a little farther.
47  *
48  * Revision 1.4  2002/05/28 04:56:51  theoddone33
49  * runs a little bit now
50  *
51  * Revision 1.3  2002/05/26 20:22:48  theoddone33
52  * Most of network/ works
53  *
54  * Revision 1.2  2002/05/04 04:36:56  theoddone33
55  * More changes, took out a lot of the sound stuff which will bite later but
56  * I don't care.
57  *
58  * Revision 1.1.1.1  2002/05/03 03:28:11  root
59  * Initial import.
60  *
61  * 
62  * 12    10/29/99 10:40p Jefff
63  * hack to make german medal names display without actually changing them
64  * 
65  * 11    9/02/99 3:41p Jefff
66  * changed badge voice handling to be similar to promotion voice handling
67  * 
68  * 10    8/26/99 8:49p Jefff
69  * Updated medals screen and about everything that ever touches medals in
70  * one way or another.  Sheesh.
71  * 
72  * 9     7/16/99 1:50p Dave
73  * 8 bit aabitmaps. yay.
74  * 
75  * 8     3/19/99 9:51a Dave
76  * Checkin to repair massive source safe crash. Also added support for
77  * pof-style nebulae, and some new weapons code.
78  * 
79  * 8     3/15/99 10:29a Neilk
80  * 
81  * 7     1/30/99 5:08p Dave
82  * More new hi-res stuff.Support for nice D3D textures.
83  * 
84  * 6     12/18/98 1:13a Dave
85  * Rough 1024x768 support for Direct3D. Proper detection and usage through
86  * the launcher.
87  * 
88  * 5     11/30/98 1:07p Dave
89  * 16 bit conversion, first run.
90  * 
91  * 4     10/23/98 3:51p Dave
92  * Full support for tstrings.tbl and foreign languages. All that remains
93  * is to make it active in Fred.
94  * 
95  * 3     10/13/98 9:29a Dave
96  * Started neatening up freespace.h. Many variables renamed and
97  * reorganized. Added AlphaColors.[h,cpp]
98  * 
99  * 2     10/07/98 10:54a Dave
100  * Initial checkin.
101  * 
102  * 1     10/07/98 10:51a Dave
103  * 
104  * 26    6/13/98 3:18p Hoffoss
105  * NOX()ed out a bunch of strings that shouldn't be translated.
106  * 
107  * 25    6/01/98 11:43a John
108  * JAS & MK:  Classified all strings for localization.
109  * 
110  * 24    5/01/98 12:34p John
111  * Added code to force FreeSpace to run in the same dir as exe and made
112  * all the parse error messages a little nicer.
113  * 
114  * 23    4/27/98 3:13p Allender
115  * make ctrl-enter work on medals screen
116  * 
117  * 22    4/23/98 8:27p Allender
118  * basic support for cutscene playback.  Into movie code in place.  Tech
119  * room can view cutscenes stored in CDROM_dir variable
120  * 
121  * 21    4/12/98 8:30p Allender
122  * minor medal changes to show number of medals if > 1
123  * 
124  * 20    4/10/98 4:51p Hoffoss
125  * Made several changes related to tooltips.
126  * 
127  * 19    3/18/98 12:03p John
128  * Marked all the new strings as externalized or not.
129  * 
130  * 18    3/11/98 5:02p Dave
131  * Put in code to support new medals artwork. Assorted multiplayer bug
132  * fixes.
133  * 
134  * 17    3/07/98 5:44p Dave
135  * Finished player info popup. Ironed out a few todo bugs.
136  * 
137  * 16    3/05/98 5:11p Allender
138  * fix up medals screen (again).  Don't do state transition when viewing
139  * medals from debriefing screen.
140  * 
141  * 15    3/05/98 2:32p Hoffoss
142  * Renamed Rank_bitmap to Rank_bm so it isn't named the same as the
143  * variable in the debrief screen which confuses the debugger.
144  * 
145  * 14    2/22/98 2:48p John
146  * More String Externalization Classification
147  * 
148  * 13    2/09/98 5:21p Hoffoss
149  * Made exit from medals screen to previous screen (instead of assuming
150  * it's the barracks) work.
151  * 
152  * 12    1/27/98 4:23p Allender
153  * enhanced internal scoring mechanisms.
154  * 
155  * 11    11/12/97 4:40p Dave
156  * Put in multiplayer campaign support parsing, loading and saving. Made
157  * command-line variables better named. Changed some things on the initial
158  * pilot select screen.
159  * 
160  * 10    11/12/97 9:30a Dave
161  * Fixed rank insignia tooltip not showing up.
162  * 
163  * 9     11/06/97 4:39p Allender
164  * a ton of medal work.  Removed an uneeded elemen in the scoring
165  * structure.  Fix up medals screen to apprioriate display medals (after
166  * mask was changed).  Fix Fred to only display medals which may actually
167  * be granted.  Added image_filename to player struct for Jason Hoffoss
168  * 
169  * 8     11/05/97 4:43p Allender
170  * reworked medal/rank system to read all data from tables.  Made Fred
171  * read medals.tbl.  Changed ai-warp to ai-warp-out which doesn't require
172  * waypoint for activation
173  *
174  * $NoKeywords: $
175  */
176
177
178 #include "medals.h"
179 #include "2d.h"
180 #include "snazzyui.h"
181 #include "bmpman.h"
182 #include "gamesequence.h"
183 #include "animplay.h"
184 #include "mouse.h"
185 #include "freespace.h"
186 #include "scoring.h"
187 #include "player.h"
188 #include "palman.h"
189 #include "ui.h"
190 #include "key.h"
191 #include "cmdline.h"
192 #include "gamesnd.h"
193 #include "alphacolors.h"
194 #include "localize.h"
195 #include "missionscreencommon.h"  // for common_set_interface_palette
196
197 //#define MAX_MEDAL_TYPES 63 // the # of medals which exist so far
198
199 /*
200 #define CALLSIGN_X 198
201 #define CALLSIGN_Y 80
202 #define CALLSIGN_W (439-CALLSIGN_X)
203 #define CALLSIGN_H (116-CALLSIGN_Y)
204 */
205
206 // define for the medal information
207 medal_stuff Medals[NUM_MEDALS];
208 badge_stuff Badge_info[MAX_BADGES];
209
210 // holds indices into Medals array of the badges for # kills
211 int Badge_index[MAX_BADGES];
212
213 // the rank section of the screen
214 #ifdef MAKE_FS1
215         // not in Medal_coords but needs to be set
216         // to not interfere with other medals
217         #define RANK_MEDAL_REGION               16                      // region number of the rank medal
218 #else
219         #define RANK_MEDAL_REGION               12                      // region number of the rank medal
220 #endif
221
222 #ifdef FS2_DEMO
223 #warning Find real FS2_DEMO spot for medals
224 #endif
225 // coords for indiv medal bitmaps
226 int Medal_coords[GR_NUM_RESOLUTIONS][NUM_MEDALS][2] = {
227         {                               // GR_640
228 #ifdef MAKE_FS1
229                 { 108, 74 },                            // Conspicuous Gallantry
230                 { 473, 73 },                            // Vasudan Alliance
231                 { 146, 150 },                           // Distinguished Flying Cross
232                 { 219, 152 },                           // Commendation Medal
233                 { 360, 150 },                           // Galatea Survivor
234                 { 432, 150 },                           // Legion of Merit
235                 { 88, 243 },                            // Meritorious Unit
236                 { 168, 243 },                           // Medal of Honor
237                 { 248, 250 },                           // Galactic Service
238                 { 328, 250 },                           // Military Defense
239                 { 406, 244 },                           // Good Conduct
240                 { 483, 243 },                           // Distinguished Service Cross
241                 { 340, 109 },                           // Ace
242                 { 373, 109 },                           // Double Ace
243 #ifndef FS1_DEMO
244                 { 403, 109 },                           // Triple Ace
245 #endif // FS1_DEMO
246                 { 287, 186 },                           // Wings
247 #else
248                 { 89, 47 },                                     // eps. peg. lib
249                 { 486, 47 },                            // imp. order o' vasuda
250                 { 129, 130 },                           // dist flying cross
251                 { 208, 132 },                           // soc service
252                 { 361, 131 },                           // dist intel cross
253                 { 439, 130 },                           // order of galatea
254                 { 64, 234 },                            // meritorious unit comm.
255                 { 153, 234 },                           // medal of valor
256                 { 239, 241 },                           // gtva leg of honor
257                 { 326, 240 },                           // allied defense citation
258                 { 411, 234 },                           // neb campaign victory
259                 { 494, 234 },                           // ntf campaign victory
260                 { 189, 80 },                            // rank
261                 { 283, 91 },                            // wings
262                 { 372, 76 },                            // bronze kills badge
263                 { 403, 76 },                            // silver kills badge
264 #ifndef FS2_DEMO
265                 { 435, 76 },                            // gold kills badge
266                 { 300, 152 },                           // SOC unit crest
267 #endif  // !FS2_DEMO
268 #endif  // MAKE_FS1
269         },
270         {                               // GR_1024
271                 { 143, 75 },                            // eps. peg. lib
272                 { 777, 75 },                            // imp. order o' vasuda
273                 { 206, 208 },                           // dist flying cross
274                 { 333, 212 },                           // soc service
275                 { 578, 210 },                           // dist intel cross
276                 { 703, 208 },                           // order of galatea
277                 { 103, 374 },                           // meritorious unit comm.
278                 { 245, 374 },                           // medal of valor
279                 { 383, 386 },                           // gtva leg of honor
280                 { 522, 384 },                           // allied defense citation
281                 { 658, 374 },                           // neb campaign victory
282                 { 790, 374 },                           // ntf campaign victory
283                 { 302, 128 },                           // rank
284                 { 453, 146 },                           // wings
285                 { 595, 121 },                           // bronze kills badge
286                 { 646, 121 },                           // silver kills badge
287 #if !(defined(FS2_DEMO) || defined(MAKE_FS1))
288                 { 696, 121 },                           // gold kills badge
289                 { 480, 244 },                           // SOC unit crest
290 #endif
291         }
292 };
293
294 #ifdef MAKE_FS1
295 // coords for the medal/rank title
296 static int Rank_label_coords[2] = {
297         240, 126                                // Rank
298 };
299
300 static int Rank_coords[2] = {
301         208, 113                                // Rank
302 };
303
304 // I couldn't think of a better way to do this so define 
305 // the base center point for each medal to center the label on
306 //
307 // x = the horizontal center point of the bitmap
308 // y = the base of the medal bitmap itself
309 static int Medals_label_coords[NUM_MEDALS][2] = {
310         // x, y
311         { 137, 158 },                           // Conspicuous Gallantry
312         { 502, 154 },                           // Vasudan Alliance
313         { 176, 238 },                           // Distinguished Flying Cross
314         { 249, 244 },                           // Commendation Medal
315         { 390, 238 },                           // Galatea Survivor
316         { 462, 237 },                           // Legion of Merit
317         { 121, 345 },                           // Meritorious Unit
318         { 199, 346 },                           // Medal of Honor
319         { 280, 349 },                           // Galactic Service
320         { 360, 350 },                           // Military Defense
321         { 438, 349 },                           // Good Conduct
322         { 517, 353 },                           // Distinguished Service Cross
323         { 352, 129 },                           // Ace
324         { 385, 129 },                           // Double Ace
325 #ifndef FS1_DEMO
326         { 415, 129 },                           // Triple Ace
327 #endif
328         { 319, 216 },                           // Wings
329 };
330 #else
331 // coords for the medal title
332 static int Medals_label_coords[GR_NUM_RESOLUTIONS][3] = {
333         { 241, 458, 300 },                      // GR_640 x, y, w
334         { 386, 734, 480 }                               // GR_1024 x, y, w
335 };
336 #endif
337
338 #define MEDALS_NUM_BUTTONS                      1
339 #define MEDALS_EXIT                                     0       
340 ui_button_info Medals_buttons[GR_NUM_RESOLUTIONS][MEDALS_NUM_BUTTONS] = {
341         { // GR_640
342 #ifdef MAKE_FS1
343                 ui_button_info("MX_17", 561,    411,    -1,     -1,     17),
344 #else
345                 ui_button_info("MEB_18",        574,    432,    -1,     -1,     18),
346 #endif
347         },
348         { // GR_1024
349                 ui_button_info("2_MEB_18",      919,    691,    -1,     -1,     18),
350         }
351 };
352
353 #ifdef MAKE_FS1
354         #define MEDALS_NUM_TEXT                         0
355 #else
356         #define MEDALS_NUM_TEXT                         1
357 #endif
358 UI_XSTR Medals_text[GR_NUM_RESOLUTIONS][MEDALS_NUM_TEXT] = {
359         {       // GR_640
360                 // not needed for FS1
361 #ifndef MAKE_FS1
362                 {"Exit",                1466,           587,    416,    UI_XSTR_COLOR_PINK, -1, &Medals_buttons[GR_640][MEDALS_EXIT].button },
363 #endif
364         },
365         {       // GR_1024
366                 // not needed for FS1
367 #ifndef MAKE_FS1
368                 {"Exit",                1466,           943,    673,    UI_XSTR_COLOR_PINK, -1, &Medals_buttons[GR_1024][MEDALS_EXIT].button },
369 #endif
370         },
371 };
372
373 static char* Medals_background_filename[GR_NUM_RESOLUTIONS] = {
374         "MedalsDisplayEmpty",
375         "2_MedalsDisplayEmpty"
376 };
377
378 static char* Medals_mask_filename[GR_NUM_RESOLUTIONS] = {
379         "Medals-m",
380         "2_Medals-m"
381 };
382
383 static int Medals_callsign_y[GR_NUM_RESOLUTIONS] = {
384 #ifdef MAKE_FS1
385         79, 89
386 #else
387         54, 89
388 #endif
389 };
390
391 scoring_struct *Player_score=NULL;
392
393 int Medals_mode;
394 player *Medals_player;
395
396 // -----------------------------------------------------------------------------
397 // Main medals screen state
398 //
399 #define NUM_MEDAL_REGIONS                       NUM_MEDALS + 1                          // the extra one is for the rank medal
400
401 static bitmap *Medals_mask;
402 int Medals_mask_w, Medals_mask_h;
403 //static int Medal_palette;              // Medal palette bitmap - no longer used
404 static int Medals_bitmap_mask;         // the mask for the medal case
405 static int Medals_bitmap;              // the medal case itself
406 static int Medal_bitmaps[NUM_MEDALS];  // bitmaps for the individual medals
407 static int Rank_bm;                                                     // bitmap for the rank medal
408
409 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
410
411 static UI_WINDOW Medals_window;
412
413 //#define MAX_MEDALS_BUTTONS                                            1
414 //#define MEDAL_BUTTON_EXIT                                             0
415 //static UI_BUTTON Medal_buttons[MAX_MEDALS_BUTTONS];
416
417 /*static char *Medal_button_names[MAX_MEDALS_BUTTONS] = {
418 //XSTR:OFF
419         "MX_17"
420 //XSTR:ON
421 };
422 */
423 /*
424 static int Medal_button_coords[MAX_MEDALS_BUTTONS][2] = {
425         {561,411}
426 };
427 static int Medal_button_masks[MAX_MEDALS_BUTTONS] = {
428         17
429 };
430 */
431
432
433 #define MEDAL_BITMAP_INIT (1<<0)
434 #define MASK_BITMAP_INIT  (1<<1)
435 int Init_flags;
436
437 void parse_medal_tbl()
438 {
439         int rval, num_medals, i, bi;
440
441         if ((rval = setjmp(parse_abort)) != 0) {
442                 Error(LOCATION, "Error parsing 'medals.tbl'\r\nError code = %i.\r\n", rval);
443         } 
444
445         // open localization
446         lcl_ext_open();
447
448         read_file_text("medals.tbl");
449
450         reset_parse();
451
452         // parse in all the rank names
453         num_medals = 0;
454         bi = 0;
455         required_string("#Medals");
456         while ( required_string_either("#End", "$Name:") ) {
457                 Assert ( num_medals < NUM_MEDALS);
458                 required_string("$Name:");
459                 stuff_string( Medals[num_medals].name, F_NAME, NULL );
460                 required_string("$Bitmap:");
461                 stuff_string( Medals[num_medals].bitmap, F_NAME, NULL );
462                 required_string("$Num mods:");
463                 stuff_int( &Medals[num_medals].num_versions);
464
465                 // some medals are based on kill counts.  When string +Num Kills: is present, we know that
466                 // this medal is a badge and should be treated specially
467                 Medals[num_medals].kills_needed = 0;
468                 if ( optional_string("+Num Kills:") ) {
469                         char buf[MULTITEXT_LENGTH + 1];
470
471                         Assert( bi < MAX_BADGES );
472                         stuff_int( &Medals[num_medals].kills_needed );
473                         Badge_index[bi] = num_medals;
474 #ifdef MAKE_FS1
475                         required_string("$Wavefile 1:");
476                         stuff_string(Badge_info[bi].voice_base, F_NAME, NULL, MAX_FILENAME_LEN);
477                         required_string("$Wavefile 2:");
478                         stuff_string(Badge_info[bi].voice_base2, F_NAME, NULL, MAX_FILENAME_LEN);
479 #elif FS2_DEMO
480 #warning FS2_DEMO HACK: Wavefile 1/2: wave1? wave2?
481                         required_string("$Wavefile 1:");
482                         stuff_string(Badge_info[bi].voice_base, F_NAME, NULL, MAX_FILENAME_LEN);
483                         required_string("$Wavefile 2:");
484                         stuff_string(Badge_info[bi].voice_base, F_NAME, NULL, MAX_FILENAME_LEN);
485                         //stuff_string(Badge_info[bi].wave2, F_NAME, NULL, MAX_FILENAME_LEN);
486 #else
487                         required_string("$Wavefile Base:");
488                         stuff_string(Badge_info[bi].voice_base, F_NAME, NULL, MAX_FILENAME_LEN);
489 #endif                  
490
491                         required_string("$Promotion Text:");
492                         stuff_string(buf, F_MULTITEXT, NULL);
493                         Badge_info[bi].promotion_text = strdup(buf);
494
495                         bi++;
496                 }
497
498                 num_medals++;
499         }
500
501         required_string("#End");
502         Assert( num_medals == NUM_MEDALS );
503
504         // be sure that the badges kill numbers show up in order
505         for (i = 0; i < MAX_BADGES-1; i++ ) {
506                 if ( Medals[Badge_index[i]].kills_needed >= Medals[Badge_index[i+1]].kills_needed ){
507                         Error(LOCATION, "Badges must appear sorted by lowest kill # first in medals.tbl\nFind Allender for most information.");
508                 }
509         }
510
511         // close localization
512         lcl_ext_close();
513 }
514
515 void medal_main_init(player *pl, int mode)
516 {
517         int idx;
518
519         Assert(pl != NULL);
520         Medals_player = pl;
521
522    Player_score = &Medals_player->stats;
523
524 #ifndef NDEBUG
525         if(Cmdline_gimme_all_medals){
526                 //int idx;
527                 for(idx=0; idx < NUM_MEDALS; idx++){
528                         Medals_player->stats.medals[idx] = 1;           
529                 }
530         }
531 #endif
532
533         Medals_mode = mode;
534
535         snazzy_menu_init();
536         Medals_window.create( 0, 0, gr_screen.max_w, gr_screen.max_h, 0 );      
537
538         // create the interface buttons
539         for (idx=0; idx<MEDALS_NUM_BUTTONS; idx++) {
540                 // create the object
541                 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);
542
543                 // set the sound to play when highlighted
544                 Medals_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
545
546                 // set the ani for the button
547                 Medals_buttons[gr_screen.res][idx].button.set_bmaps(Medals_buttons[gr_screen.res][idx].filename);
548
549                 // set the hotspot
550                 Medals_buttons[gr_screen.res][idx].button.link_hotspot(Medals_buttons[gr_screen.res][idx].hotspot);
551         }       
552
553         // add all xstrs
554         for (idx=0; idx<MEDALS_NUM_TEXT; idx++) {
555                 Medals_window.add_XSTR(&Medals_text[gr_screen.res][idx]);
556         }
557
558
559         Init_flags = 0; 
560
561         //init_medal_palette();
562 #ifdef MAKE_FS1
563         common_set_interface_palette("MedalsPalette");
564 #endif
565         
566         Medals_bitmap = bm_load(Medals_background_filename[gr_screen.res]);
567         if (Medals_bitmap < 0) {
568            Error(LOCATION, "Error loading medal background bitmap %s", Medals_background_filename[gr_screen.res]);
569         } else {
570                 Init_flags |= MEDAL_BITMAP_INIT;
571         }
572
573         Medals_mask_w = -1;
574         Medals_mask_h = -1;
575       
576         Medals_bitmap_mask = bm_load(Medals_mask_filename[gr_screen.res]);
577         if(Medals_bitmap_mask < 0){
578                 Error(LOCATION, "Error loading medal mask file %s", Medals_mask_filename[gr_screen.res]);
579         } else {
580                 Init_flags |= MASK_BITMAP_INIT;
581                 Medals_mask = bm_lock(Medals_bitmap_mask, 8, BMP_AABITMAP);
582                 bm_get_info(Medals_bitmap_mask, &Medals_mask_w, &Medals_mask_h);
583         }
584         init_medal_bitmaps();
585         init_snazzy_regions();
586
587         gr_set_color_fast(&Color_normal);
588
589         Medals_window.set_mask_bmap(Medals_mask_filename[gr_screen.res]);
590 }
591
592 // this is just a hack to display translated names without actually changing the names, 
593 // which would break stuff
594 void medals_translate_name(char *name, int max_len)
595 {
596 #ifdef MAKE_FS1
597         if (!strcmp(name, "Conspicuous Gallantry")) {
598                 strncpy(name, "Tapferkeitsmedaille", max_len);
599
600         } else if (!strcmp(name, "Vasudan Alliance")) {
601                 strncpy(name, "Vasudanischen Allianz", max_len);
602
603         } else if (!strcmp(name, "Distinguished Flying Cross")) {
604                 strncpy(name, "Kreuz f\x81r Fliegerleistungen", max_len);
605
606         } else if (!strcmp(name, "Commendation Medal")) {
607                 strncpy(name, "Anerkennungsmedaille", max_len);
608
609         } else if (!strcmp(name, "Galatea Survivor")) {
610                 strncpy(name, "Galatea-\x9A""berlebender", max_len);
611
612         } else if (!strcmp(name, "Legion of Merit")) {
613                 strncpy(name, "Verdienstlegion", max_len);
614
615         } else if (!strcmp(name, "Meritorious Unit")) {
616                 strncpy(name, "Verdienstmedaille", max_len);
617
618         } else if (!strcmp(name, "Medal of Honor")) {
619                 strncpy(name, "Ehrenmedaille", max_len);
620
621         } else if (!strcmp(name, "Galactic Service")) {
622                 strncpy(name, "Galaktischer Dienst", max_len);
623
624         } else if (!strcmp(name, "Military Defense")) {
625                 strncpy(name, "Verteidigungsmedaille", max_len);
626
627         } else if (!strcmp(name, "Good Conduct")) {
628                 strncpy(name, "Medaille f\x81r gute F\x81hrung", max_len);
629
630         } else if (!strcmp(name, "Distinguished Service Cross")) {
631                 strncpy(name, "Kreuz f\x81r Einsatz", max_len);
632
633         } else if (!strcmp(name, "Ace")) {
634                 strncpy(name, "Bronzener Stern", max_len);
635
636         } else if (!strcmp(name, "Double Ace")) {
637                 strncpy(name, "Silberner Stern", max_len);
638
639         } else if (!strcmp(name, "Triple Ace")) {
640                 strncpy(name, "Goldener Stern", max_len);
641
642         } else if (!strcmp(name, "Wings")) {
643                 strncpy(name, "Pilotenabzeichen", max_len);
644
645         } else if (!strcmp(name, "Rank")) {
646                 strncpy(name, "Dienstgrad", max_len);
647         }
648 #else
649         if (!strcmp(name, "Epsilon Pegasi Liberation")) {
650                 strncpy(name, "Epsilon Pegasi Befreiungsmedaille", max_len);
651
652         } else if (!strcmp(name, "Imperial Order of Vasuda")) {
653                 strncpy(name, "Imperialer Orden von Vasuda ", max_len);
654
655         } else if (!strcmp(name, "Distinguished Flying Cross")) {
656                 strncpy(name, "Fliegerkreuz Erster Klasse", max_len);
657
658         } else if (!strcmp(name, "SOC Service Medallion")) {
659                 strncpy(name, "SEK-Dienstmedaille ", max_len);
660
661         } else if (!strcmp(name, "Intelligence Cross")) {
662                 strncpy(name, "Geheimdienstkreuz am Bande", max_len);
663
664         } else if (!strcmp(name, "Order of Galatea")) {
665                 strncpy(name, "Orden von Galatea ", max_len);
666
667         } else if (!strcmp(name, "Meritorious Unit Commendation")) {
668                 strncpy(name, "Ehrenspange der Allianz", max_len);
669
670         } else if (!strcmp(name, "Medal of Valor")) {
671                 strncpy(name, "Tapferkeitsmedaille ", max_len);
672
673         } else if (!strcmp(name, "GTVA Legion of Honor")) {
674                 strncpy(name, "Orden der GTVA-Ehrenlegion", max_len);
675
676         } else if (!strcmp(name, "Allied Defense Citation")) {
677                 strncpy(name, "Alliierte Abwehrspange ", max_len);
678
679         } else if (!strcmp(name, "Nebula Campaign Victory Star")) {
680                 strncpy(name, "Nebel-Siegesstern", max_len);
681
682         } else if (!strcmp(name, "NTF Campaign Victory Star")) {
683                 strncpy(name, "NTF-Siegesstern ", max_len);
684
685         } else if (!strcmp(name, "Rank")) {
686                 strncpy(name, "Dienstgrad", max_len);
687
688         } else if (!strcmp(name, "Wings")) {
689                 strncpy(name, "Fliegerspange", max_len);
690
691         } else if (!strcmp(name, "Ace")) {
692                 strncpy(name, "Flieger-As", max_len);
693
694         } else if (!strcmp(name, "Double Ace")) {
695                 strncpy(name, "Doppel-As ", max_len);
696
697         } else if (!strcmp(name, "Triple Ace")) {
698                 strncpy(name, "Dreifach-As ", max_len);
699
700         } else if (!strcmp(name, "SOC Unit Crest")) {
701                 strncpy(name, "SEK-Abzeichen ", max_len);
702         }
703 #endif
704 }
705
706 // this is just a hack to display translated names without actually changing the names, 
707 // which would break stuff
708 void medals_translate_name_pl(char *name, int max_len)
709 {
710         if (!strcmp(name, "Epsilon Pegasi Liberation")) {
711                 strncpy(name, "Order Wyzwolenia Epsilon Pegasi", max_len);
712
713         } else if (!strcmp(name, "Imperial Order of Vasuda")) {
714                 strncpy(name, "Imperialny Order Vasudy", max_len);
715
716         } else if (!strcmp(name, "Distinguished Flying Cross")) {
717                 strncpy(name, "Krzy\xBF Wybitnego Pilota", max_len);
718
719         } else if (!strcmp(name, "SOC Service Medallion")) {
720                 strncpy(name, "Krzy\xBF S\xB3u\xBF\x62 Specjalnych", max_len);
721
722         } else if (!strcmp(name, "Intelligence Cross")) {
723                 strncpy(name, "Krzy\xBF Wywiadu", max_len);
724
725         } else if (!strcmp(name, "Order of Galatea")) {
726                 strncpy(name, "Order Galatei", max_len);
727
728         } else if (!strcmp(name, "Meritorious Unit Commendation")) {
729                 strncpy(name, "Medal Pochwalny", max_len);
730
731         } else if (!strcmp(name, "Medal of Valor")) {
732                 strncpy(name, "Medal za Odwag\xEA", max_len);
733
734         } else if (!strcmp(name, "GTVA Legion of Honor")) {
735                 strncpy(name, "Legia Honorowa GTVA", max_len);
736
737         } else if (!strcmp(name, "Allied Defense Citation")) {
738                 strncpy(name, "Order za Obron\xEA Sojuszu", max_len);
739
740         } else if (!strcmp(name, "Nebula Campaign Victory Star")) {
741                 strncpy(name, "Gwiazda Wiktorii Kampanii w Mg\xB3\x61wicy", max_len);
742
743         } else if (!strcmp(name, "NTF Campaign Victory Star")) {
744                 strncpy(name, "Gwiazda Wiktorii Kampanii NTF", max_len);
745
746         } else if (!strcmp(name, "Rank")) {
747                 strncpy(name, "Ranga", max_len);
748
749         } else if (!strcmp(name, "Wings")) {
750                 strncpy(name, "Skrzyd\xB3\x61", max_len);
751
752         } else if (!strcmp(name, "Ace")) {
753                 strncpy(name, "As", max_len);   
754
755         } else if (!strcmp(name, "Double Ace")) {
756                 strncpy(name, "Podw\xF3jny As", max_len);
757
758         } else if (!strcmp(name, "Triple Ace")) {
759                 strncpy(name, "Potr\xF3jny As", max_len);
760                 
761         } else if (!strcmp(name, "SOC Unit Crest")) {
762                 strncpy(name, "Tarcza S\xB3u\xBF\x62 Specjalnych", max_len);    
763         }
764 }
765
766 #ifdef MAKE_FS1
767 void blit_label(char *label, int *coordsx, int *coordsy, int num)
768 #else
769 void blit_label(char *label, int *coords, int num)
770 #endif
771 {
772         int x, y, sw;
773         char text[256];
774
775         gr_set_color_fast(&Color_bright);
776
777         // translate medal names before displaying
778         // cant translate in table cuz the names are used in comparisons
779         if (Lcl_gr) {
780                 char translated_label[256];
781                 strncpy(translated_label, label, 256);
782                 medals_translate_name(translated_label, 256);
783
784                 // set correct string
785                 if ( num > 1 ) {
786                         sprintf( text, NOX("%s (%d)"), translated_label, num );
787                 } else {
788                         sprintf( text, "%s", translated_label );
789                 }
790         } else if(Lcl_pl) {
791                 char translated_label[256];
792                 strncpy(translated_label, label, 256);
793                 medals_translate_name_pl(translated_label, 256);
794
795                 // set correct string
796                 if ( num > 1 ) {
797                         sprintf( text, NOX("%s (%d)"), translated_label, num );
798                 } else {
799                         sprintf( text, "%s", translated_label );
800                 }
801         } else {
802                 // set correct string
803                 if ( num > 1 ) {
804                         sprintf( text, NOX("%s (%d)"), label, num );
805                 } else {
806                         sprintf( text, "%s", label );
807                 }
808         }
809
810         // find correct coords
811         gr_get_string_size(&sw, NULL, text);
812 #ifdef MAKE_FS1
813         x = *coordsx - sw / 2;
814         y = *coordsy + 8;
815 #else
816         x = Medals_label_coords[gr_screen.res][0] + (Medals_label_coords[gr_screen.res][2] - sw) / 2;
817         y = Medals_label_coords[gr_screen.res][1];
818 #endif
819
820         // do it
821         gr_string(x, y, text);
822 }
823
824 void blit_callsign()
825 {
826 #ifdef MAKE_FS1
827         gr_set_color_fast(&Color_bright_blue);
828 #else
829         gr_set_color_fast(&Color_normal);
830 #endif
831
832         // nothing special, just do it.
833         gr_string(0x8000, Medals_callsign_y[gr_screen.res], Medals_player->callsign);
834 }
835
836 int medal_main_do()
837 {
838    int region,selected, k;
839
840         k = Medals_window.process();    
841
842         // process an exit command
843         if ((k == KEY_ESC) && (Medals_mode == MM_NORMAL)) {
844                 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
845         }
846
847         // draw the background medal display case
848         gr_reset_clip();
849         GR_MAYBE_CLEAR_RES(Medals_bitmap);
850         if(Medals_bitmap != -1){
851                 gr_set_bitmap(Medals_bitmap);
852                 gr_bitmap(0,0);
853         }
854
855         // check to see if a button was pressed
856         if( (k == (KEY_CTRLED|KEY_ENTER)) || (Medals_buttons[gr_screen.res][MEDALS_EXIT].button.pressed()) ) {  
857                 gamesnd_play_iface(SND_COMMIT_PRESSED);
858                 if(Medals_mode == MM_NORMAL){
859                         gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
860                 } else {
861                         // any calling popup function will know to close the screen down
862                         return 0;
863                 }               
864         }
865
866         // blit medals also takes care of blitting the rank insignia
867         blit_medals(); 
868         blit_callsign();        
869         
870         region = snazzy_menu_do((ubyte*)Medals_mask->data, Medals_mask_w, Medals_mask_h, NUM_MEDAL_REGIONS, Medal_regions, &selected);
871         switch (region) {
872                 case ESC_PRESSED:
873                         if (Medals_mode == MM_NORMAL) {
874                                 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
875                         } else {
876                                 // any calling popup function will know to close the screen down
877                                 return 0;
878                         }
879                         break;
880
881                 case RANK_MEDAL_REGION :
882 #ifdef MAKE_FS1
883                         blit_label(Ranks[Player_score->rank].name, &Rank_label_coords[0], &Rank_label_coords[1], 1);
884 #else
885                         blit_label(Ranks[Player_score->rank].name, &Medal_coords[gr_screen.res][region][0], 1);
886 #endif
887                         break;
888
889                 case -1:
890                         break;
891
892                 default :
893         if (Player_score->medals[region] > 0){
894 #ifdef MAKE_FS1
895                                 blit_label(Medals[region].name, &Medals_label_coords[region][0], &Medals_label_coords[region][1], Player_score->medals[region] );
896 #else
897                                 blit_label(Medals[region].name, &Medal_coords[gr_screen.res][region][0], Player_score->medals[region] );
898 #endif
899                         }
900                         break;
901         } // end switch
902
903         Medals_window.draw();
904
905         gr_flip();
906
907         return 1;
908 }
909
910 void medal_main_close()
911 {
912         int idx;
913         if (Init_flags & MEDAL_BITMAP_INIT)
914                 bm_unload(Medals_bitmap);
915
916         if (Init_flags & MASK_BITMAP_INIT) {
917                 bm_unlock(Medals_bitmap_mask);
918                 bm_unload(Medals_bitmap_mask);
919         }
920
921    for (idx=0; idx < NUM_MEDALS; idx++) {
922                 if (Medal_bitmaps[idx] > -1){
923                         bm_unload(Medal_bitmaps[idx]);
924                 }
925         }
926
927    Player_score = NULL;
928         Medals_window.destroy();
929
930 #ifdef MAKE_FS1
931         common_free_interface_palette();
932 #endif
933
934         snazzy_menu_close();
935         palette_restore_palette();
936 }
937
938 // free up memory from table parsing
939 void medal_tbl_close()
940 {
941         int i;
942         
943         for (i=0; i<MAX_BADGES; i++) {
944                 if (Badge_info[i].promotion_text) {
945                         free(Badge_info[i].promotion_text);
946                         Badge_info[i].promotion_text = NULL;
947                 }
948         }
949 }
950
951 /*
952 void init_medal_palette()
953 {
954         Medal_palette = bm_load("MedalsPalette.pcx");
955         if(Medal_palette > -1){
956 #ifndef HARDWARE_ONLY
957                 palette_use_bm_palette(Medal_palette);
958 #endif
959         }
960 }
961 */
962
963 // function to load in the medals for this player.  It loads medals that the player has (known
964 // by whether or not a non-zero number is present in the player's medal array), then loads the
965 // rank bitmap
966
967 void init_medal_bitmaps()
968 {
969         int idx;
970         Assert(Player_score);
971
972         for (idx=0; idx<NUM_MEDALS; idx++) {
973                 Medal_bitmaps[idx] = -1;
974                 if (Player_score->medals[idx] > 0) {
975                         int num_medals;
976                         char filename[NAME_LENGTH], base[NAME_LENGTH];
977                         
978                         // possibly load a different filename that is specified by the bitmap filename
979                         // for this medal.  if the player has > 1 of these types of medals, then determien
980                         // which of the possible version to use based on the player's count of this medal
981                         strcpy( filename, Medals[idx].bitmap );
982
983                         _splitpath( filename, NULL, NULL, base, NULL );
984
985                         num_medals = Player_score->medals[idx];
986
987                         // can't display more than the maximum number of version for this medal
988                         if ( num_medals > Medals[idx].num_versions )
989                                 num_medals = Medals[idx].num_versions;
990
991                         if ( num_medals > 1 ) {
992                                 // append the proper character onto the end of the medal filename.  Base version
993                                 // has no character. next version is a, then b, etc.
994                                 sprintf( base, "%s%c", base, (num_medals-2)+'a');
995                         }
996         
997                         // hi-res support
998                         if (gr_screen.res == GR_1024) {
999                                 sprintf( filename, "2_%s", base );
1000                         }
1001
1002                         // base now contains the actual medal bitmap filename needed to load
1003                         // we don't need to pass extension to bm_load anymore, so just use the basename
1004                         // as is.
1005          Medal_bitmaps[idx] = bm_load( filename );
1006                         Assert( Medal_bitmaps[idx] != -1 );
1007                 }
1008         }
1009
1010         // load up rank insignia
1011         if (gr_screen.res == GR_1024) {
1012                 char filename[NAME_LENGTH];
1013                 sprintf(filename, "2_%s", Ranks[Player_score->rank].bitmap);
1014                 Rank_bm = bm_load(filename);
1015         } else {
1016                 Rank_bm = bm_load(Ranks[Player_score->rank].bitmap);
1017         }
1018 }
1019
1020 void init_snazzy_regions()
1021 {
1022         int idx;
1023
1024         // snazzy regions for the medals/ranks, etc.
1025         for (idx=0; idx<NUM_MEDALS; idx++) {
1026                 if (idx == RANK_MEDAL_REGION) 
1027                         continue;
1028
1029                 snazzy_menu_add_region(&Medal_regions[idx], "", idx, 0);
1030         }
1031
1032         // add the rank medal region
1033         snazzy_menu_add_region(&Medal_regions[RANK_MEDAL_REGION], "", RANK_MEDAL_REGION,0);
1034 }
1035
1036
1037 // blit the medals -- this includes the rank insignia
1038 void blit_medals()
1039 {
1040         int idx;
1041
1042         for (idx=0; idx<NUM_MEDALS; idx++) {
1043                 if (Player_score->medals[idx] > 0) {
1044                         gr_set_bitmap(Medal_bitmaps[idx]);
1045                         gr_bitmap(Medal_coords[gr_screen.res][idx][0], Medal_coords[gr_screen.res][idx][1]);
1046                 }
1047         }
1048
1049         // now blit rank, since that "medal" doesnt get loaded (or drawn) the normal way
1050         gr_set_bitmap(Rank_bm);
1051 #ifdef MAKE_FS1
1052         gr_bitmap(Rank_coords[0], Rank_coords[1]);
1053 #else
1054         gr_bitmap(Medal_coords[gr_screen.res][RANK_MEDAL_REGION][0], Medal_coords[gr_screen.res][RANK_MEDAL_REGION][1]);
1055 #endif
1056 }