2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/Network/multi_pinfo.cpp $
16 * Revision 1.6 2005/03/29 02:18:47 taylor
17 * Various 64-bit platform fixes
18 * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
19 * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
20 * Streaming audio support (big thanks to Pierre Willenbrock!!)
21 * Removed dependance on strings.tbl for FS1 since we don't actually need it now
23 * Revision 1.5 2004/09/20 01:31:44 theoddone33
26 * Revision 1.4 2003/05/25 02:30:43 taylor
29 * Revision 1.3 2002/06/09 04:41:23 relnev
30 * added copyright header
32 * Revision 1.2 2002/05/07 03:16:47 theoddone33
33 * The Great Newline Fix
35 * Revision 1.1.1.1 2002/05/03 03:28:10 root
39 * 15 9/10/99 9:44p Dave
40 * Bumped version # up. Make server reliable connects not have such a huge
43 * 14 8/30/99 5:01p Dave
44 * Made d3d do less state changing in the nebula. Use new chat server for
47 * 13 8/22/99 5:53p Dave
48 * Scoring fixes. Added self destruct key. Put callsigns in the logfile
49 * instead of ship designations for multiplayer players.
51 * 12 8/03/99 11:43a Dave
52 * Don't allow medals button in demo.
54 * 11 7/26/99 11:14a Andsager
55 * Disable medals in demo multiplayer
57 * 10 6/16/99 4:06p Dave
58 * New pilot info popup. Added new draw-bitmap-as-poly function.
60 * 9 1/30/99 1:29a Dave
61 * Fixed nebula thumbnail problem. Full support for 1024x768 choose pilot
62 * screen. Fixed beam weapon death messages.
64 * 8 1/14/99 6:06p Dave
65 * 100% full squad logo support for single player and multiplayer.
67 * 7 1/12/99 4:07a Dave
68 * Put in barracks code support for selecting squad logos. Properly
69 * distribute squad logos in a multiplayer game.
71 * 6 12/14/98 12:13p Dave
72 * Spiffed up xfer system a bit. Put in support for squad logo file xfer.
75 * 5 11/30/98 1:07p Dave
76 * 16 bit conversion, first run.
78 * 4 11/05/98 4:18p Dave
79 * First run nebula support. Beefed up localization a bit. Removed all
80 * conditional compiles for foreign versions. Modified mission file
83 * 3 10/13/98 9:29a Dave
84 * Started neatening up freespace.h. Many variables renamed and
85 * reorganized. Added AlphaColors.[h,cpp]
87 * 2 10/07/98 10:53a Dave
90 * 1 10/07/98 10:50a Dave
99 #include "freespace.h"
100 #include "gamesequence.h"
106 #include "multi_xfer.h"
107 #include "multi_pinfo.h"
108 #include "alphacolors.h"
109 #include "localize.h"
112 // ---------------------------------------------------------------------------------------
113 // MULTI PLAYER INFO DEFINES/VARS
118 #define MULTI_PINFO_NUM_BUTTONS 4
121 const char *Multi_pinfo_bitmap_name[GR_NUM_RESOLUTIONS] = {
125 const char *Multi_pinfo_bitmap_mask[GR_NUM_RESOLUTIONS] = {
131 #define MPI_SCROLL_STATS_UP 0
132 #define MPI_SCROLL_STATS_DOWN 1
136 // pilot image area defs
137 int Multi_pinfo_pilot_coords[GR_NUM_RESOLUTIONS][4] = {
149 int Multi_pinfo_squad_coords[GR_NUM_RESOLUTIONS][4] = {
159 typedef struct np_bitmap {
160 int bitmap; // bitmap id
161 char filename[MAX_FILENAME_LEN]; // filename
163 np_bitmap Mp_pilot; // pilot pic
164 np_bitmap Mp_squad; // squad logo
166 UI_WINDOW Multi_pinfo_window; // the window object for the join screen
167 UI_BUTTON Multi_pinfo_select_button; // for selecting list items
168 int Multi_pinfo_bitmap; // the background bitmap
169 ui_button_info Multi_pinfo_buttons[GR_NUM_RESOLUTIONS][MULTI_PINFO_NUM_BUTTONS] = {
172 ui_button_info("PIB_00", 180, 209, -1, -1, 0),
173 ui_button_info("PIB_01", 180, 252, -1, -1, 1),
174 ui_button_info("PIB_02", 136, 295, -1, -1, 2),
175 ui_button_info("PIB_03", 583, 326, -1, -1, 3),
177 ui_button_info("PIB_00", 617, 256, -1, -1, 0),
178 ui_button_info("PIB_01", 617, 298, -1, -1, 1),
179 ui_button_info("PIB_02", 172, 322, -1, -1, 2),
180 ui_button_info("PIB_03", 219, 332, 217, 318, 3)
184 ui_button_info("2_PIB_00", 988, 410, -1, -1, 0),
185 ui_button_info("2_PIB_01", 988, 477, -1, -1, 1),
186 ui_button_info("2_PIB_02", 276, 516, -1, -1, 2),
187 ui_button_info("2_PIB_03", 350, 532, 348, 510, 3)
192 #define MULTI_PINFO_NUM_TEXT 1
194 UI_XSTR Multi_pinfo_text[GR_NUM_RESOLUTIONS][MULTI_PINFO_NUM_TEXT] = {
196 { "Close", 428, 217, 318, UI_XSTR_COLOR_PINK, -1, &Multi_pinfo_buttons[0][MPI_EXIT].button },
199 { "Close", 428, 348, 510, UI_XSTR_COLOR_PINK, -1, &Multi_pinfo_buttons[1][MPI_EXIT].button },
207 #define MULTI_PINFO_NUM_STATS_LABELS 9
209 #define MPI_MISSIONS_FLOWN 1
210 #define MPI_FLIGHT_TIME 2
211 #define MPI_LAST_FLOWN 3
212 #define MPI_FIGHTER_KILLS 4
213 // #define MPI_OTHER_KILLS 5
214 #define MPI_PSHOTS_FIRED 5
215 //#define MPI_PSHOTS_HIT 6
216 #define MPI_PSHOTS_PCT 6
217 #define MPI_SSHOTS_FIRED 7
218 // #define MPI_SSHOTS_HIT 10
219 #define MPI_SSHOTS_PCT 8
221 char *Multi_pinfo_stats_labels[MULTI_PINFO_NUM_STATS_LABELS];
223 #define MAX_LABEL_TEXT 50
224 char Multi_pinfo_stats_vals[MULTI_PINFO_NUM_STATS_LABELS][MAX_LABEL_TEXT];
225 int Multi_pinfo_stats_label_offsets[MULTI_PINFO_NUM_STATS_LABELS] = {
226 20,10,10,20,20,10,20,10,10,
230 int Multi_pinfo_stats_area_coords[GR_NUM_RESOLUTIONS][4] = {
242 int Multi_pinfo_stats_x[GR_NUM_RESOLUTIONS] = {
247 // is the popup already running
248 int Multi_pinfo_popup_running = 0;
250 // background bitmap to be blitted
251 int Multi_pinfo_screen_save = -1;
253 // flag indicating if the popup has gotten messed up somewhere and should bail
254 int Multi_pinfo_popup_error = 0;
256 // flag indicating if the popup should be done
257 int Multi_pinfo_popup_done = 0;
259 // player this popup is being used for
260 net_player *Multi_pinfo_popup_player = NULL;
263 extern shader Grey_shader;
265 // hardware textures backup
266 int Multi_pinfo_hardware_texture_backup;
269 // ---------------------------------------------------------------------------------------
270 // MULTI PLAYER INFO FORWARD DECLARATIONS
273 // initialize all popup details (graphics, etc)
274 void multi_pinfo_popup_init(net_player *pl);
276 // run the popup in a tight loop (no states)
277 void multi_pinfo_popup_do();
280 void multi_pinfo_popup_close();
282 // blit the pilot image
283 void multi_pinfo_blit_pilot_image();
285 // blit the pilot squadron logo
286 void multi_pinfo_blit_squadron_logo();
288 // blit the player statistics
289 void multi_pinfo_blit_player_stats();
291 // check for button presses
292 void multi_pinfo_popup_check_buttons();
294 // act on a button press
295 void multi_pinfo_popup_button_pressed(int n);
297 // display the medals screen for this player
298 void multi_pinfo_do_medals();
300 // load up and use the proper palette
301 void multi_pinfo_set_palette();
303 // build the stats value strings for this player
304 void multi_pinfo_build_stats();
306 // if the pilot's image was currently loading when we started the popup, load it up now if its finished
307 void multi_pinfo_maybe_reload_pic(np_bitmap *b);
309 // reset the player infomation for this popup
310 void multi_pinfo_reset_player(net_player *np);
312 // lookup the "previous" player in the netplayer list, return null if not found
313 net_player *multi_pinfo_get_prev_player(net_player *np);
315 // lookup the "next" player in the netplayer list, return null if not found
316 net_player *multi_pinfo_get_next_player(net_player *np);
319 // ---------------------------------------------------------------------------------------
320 // MULTI PLAYER INFO FUNCTIONS
323 // fire up the player info popup, select first available pilot if np == NULL
324 void multi_pinfo_popup(net_player *np)
326 // if the popup is already running, don't do anything
327 if(Multi_pinfo_popup_running){
331 // set the player for informational purposes
332 SDL_assert(np != NULL);
334 // play the popup appear sound
335 gamesnd_play_iface(SND_POPUP_APPEAR);
337 // initialize the popup
338 multi_pinfo_popup_init(np);
340 // mark the popup as running
341 Multi_pinfo_popup_running = 1;
344 multi_pinfo_popup_do();
347 multi_pinfo_popup_close();
349 // play the popup disappear sound
350 gamesnd_play_iface(SND_POPUP_DISAPPEAR);
353 // notify the popup that a player has left
354 void multi_pinfo_notify_drop(net_player *np)
358 // if we're no active, bail
359 if(!Multi_pinfo_popup_running){
363 // if this is not the player we're currently displaying, bail
364 if(np != Multi_pinfo_popup_player){
368 // otherwise we need to switch to someone else
369 reset = multi_pinfo_get_prev_player(np);
371 multi_pinfo_reset_player(reset);
374 reset = multi_pinfo_get_next_player(np);
376 multi_pinfo_reset_player(reset);
380 // bail, since there's no one else
382 Multi_pinfo_popup_done = 1;
386 // ---------------------------------------------------------------------------------------
387 // MULTI PLAYER INFO FORWARD DEFINITIONS
390 // initialize all popup details (graphics, etc)
391 void multi_pinfo_popup_init(net_player *np)
395 // no errors to start with
396 Multi_pinfo_popup_error = 0;
399 Multi_pinfo_popup_done = 0;
401 // store the background as it currently is
402 Multi_pinfo_screen_save = gr_save_screen();
403 if(Multi_pinfo_screen_save == -1){
404 Multi_pinfo_popup_error = 1;
408 // create the interface window
409 Multi_pinfo_window.create(0,0,gr_screen.max_w,gr_screen.max_h,0);
410 Multi_pinfo_window.set_mask_bmap(Multi_pinfo_bitmap_mask[gr_screen.res]);
412 // load the background bitmap
413 Multi_pinfo_bitmap = bm_load(Multi_pinfo_bitmap_name[gr_screen.res]);
414 if(Multi_pinfo_bitmap < 0){
415 Multi_pinfo_popup_error = 1;
419 // backup hardware textures setting and bash to max
420 Multi_pinfo_hardware_texture_backup = Detail.hardware_textures;
421 Detail.hardware_textures = MAX_DETAIL_LEVEL;
424 Mp_pilot.bitmap = -1;
425 SDL_strlcpy(Mp_pilot.filename, "", SDL_arraysize(Mp_pilot.filename));
426 Mp_squad.bitmap = -1;
427 SDL_strlcpy(Mp_squad.filename, "", SDL_arraysize(Mp_squad.filename));
429 // set the player status
430 multi_pinfo_reset_player(np);
432 // create the interface buttons
433 for(idx=0;idx<MULTI_PINFO_NUM_BUTTONS;idx++){
435 Multi_pinfo_buttons[gr_screen.res][idx].button.create(&Multi_pinfo_window, "", Multi_pinfo_buttons[gr_screen.res][idx].x, Multi_pinfo_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
437 // set the sound to play when highlighted
438 Multi_pinfo_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
440 // set the ani for the button
441 Multi_pinfo_buttons[gr_screen.res][idx].button.set_bmaps(Multi_pinfo_buttons[gr_screen.res][idx].filename);
444 Multi_pinfo_buttons[gr_screen.res][idx].button.link_hotspot(Multi_pinfo_buttons[gr_screen.res][idx].hotspot);
449 for(idx=0; idx<MULTI_PINFO_NUM_TEXT; idx++){
450 Multi_pinfo_window.add_XSTR(&Multi_pinfo_text[gr_screen.res][idx]);
454 // disable medals button for the demo
455 #if defined(FS2_DEMO) || defined(FS1_DEMO)
456 Multi_pinfo_buttons[gr_screen.res][MPI_MEDALS].button.hide();
457 Multi_pinfo_buttons[gr_screen.res][MPI_MEDALS].button.disable();
460 // initialize strings
461 Multi_pinfo_stats_labels[0] = strdup(XSTR("Rank", 1007));
462 Multi_pinfo_stats_labels[1] = strdup(XSTR("Missions Flown", 1008));
463 Multi_pinfo_stats_labels[2] = strdup(XSTR("Flight Time", 1009));
464 Multi_pinfo_stats_labels[3] = strdup(XSTR("Last Flown",1010));
465 Multi_pinfo_stats_labels[4] = strdup(XSTR("Total Kills", 115));
466 Multi_pinfo_stats_labels[5] = strdup(XSTR("Primary Shots Fired", 1012));
467 Multi_pinfo_stats_labels[6] = strdup(XSTR("Primary Hit %", 1013));
468 Multi_pinfo_stats_labels[7] = strdup(XSTR("Secondary Shots Fired", 1014));
469 Multi_pinfo_stats_labels[8] = strdup(XSTR("Secondary Hit %", 1015));
472 // run the popup in a tight loop (no states)
473 void multi_pinfo_popup_do()
477 // if there was an error in initialization, return immediately
478 if(Multi_pinfo_popup_error){
483 while(!Multi_pinfo_popup_done){
484 multi_pinfo_maybe_reload_pic(&Mp_pilot);
485 multi_pinfo_maybe_reload_pic(&Mp_squad);
487 // process the window
488 k = Multi_pinfo_window.process();
491 Multi_pinfo_popup_done = 1;
495 // check button presses
496 multi_pinfo_popup_check_buttons();
498 // set frametime and run background stuff
499 game_set_frametime(-1);
500 game_do_state_common(gameseq_get_state());
502 // draw the background bitmap and the ui window over it
503 SDL_assert(Multi_pinfo_screen_save != -1);
505 gr_restore_screen(Multi_pinfo_screen_save);
508 gr_set_shader(&Grey_shader);
509 gr_shade(0,0,gr_screen.clip_width, gr_screen.clip_height);
511 // draw the background bitmap
512 gr_set_bitmap(Multi_pinfo_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
515 // blit the selected pilot image
516 multi_pinfo_blit_pilot_image();
518 // blit the squadron logo
519 multi_pinfo_blit_squadron_logo();
521 // blit the player statistics
522 multi_pinfo_blit_player_stats();
524 // draw the ui window and flip
525 Multi_pinfo_window.draw();
531 void multi_pinfo_popup_close()
535 // unload any bitmaps
536 if(Multi_pinfo_bitmap != -1){
537 bm_release(Multi_pinfo_bitmap);
540 // free the background screen if possible
541 if(Multi_pinfo_screen_save >= 0){
542 gr_free_screen(Multi_pinfo_screen_save);
545 // release the pilot/squad images
546 if(Mp_pilot.bitmap != -1){
547 bm_release(Mp_pilot.bitmap);
549 if(Mp_squad.bitmap != -1){
550 bm_release(Mp_squad.bitmap);
554 for(idx=0; idx<MULTI_PINFO_NUM_STATS_LABELS; idx++){
555 if(Multi_pinfo_stats_labels[idx] != NULL){
556 free(Multi_pinfo_stats_labels[idx]);
557 Multi_pinfo_stats_labels[idx] = NULL;
561 // unset the player handle
562 Multi_pinfo_popup_player = NULL;
564 // mark the popup as not running
565 Multi_pinfo_popup_running = 0;
567 // destroy the UI_WINDOW
568 Multi_pinfo_window.destroy();
570 // restore hardware textures detail level
571 Detail.hardware_textures = Multi_pinfo_hardware_texture_backup;
574 // blit the pilot image
575 void multi_pinfo_blit_pilot_image()
577 char place_text[100];
580 // if we don't have a bitmap handle, blit a placeholder
581 if(Mp_pilot.bitmap == -1){
582 gr_set_color_fast(&Color_normal);
584 // if there is no image
585 if(strlen(Mp_pilot.filename) <= 0){
586 SDL_strlcpy(place_text, XSTR("No/Invalid Image", 1053), SDL_arraysize(place_text));
588 // if the image is xferring
589 else if(multi_xfer_lookup(Mp_pilot.filename)){
590 SDL_strlcpy(place_text, XSTR("Image Transferring", 691), SDL_arraysize(place_text));
592 // if we're not accepting images
593 else if(!(Net_player->p_info.options.flags & MLO_FLAG_ACCEPT_PIX) || !(Netgame.options.flags & MSO_FLAG_ACCEPT_PIX)){
594 SDL_strlcpy(place_text, XSTR("No Image", 692), SDL_arraysize(place_text));
598 SDL_strlcpy(place_text, XSTR("Waiting", 690), SDL_arraysize(place_text));
602 gr_get_string_size(&w,NULL,place_text);
603 gr_string(Multi_pinfo_pilot_coords[gr_screen.res][0] + ((Multi_pinfo_pilot_coords[gr_screen.res][2] - w)/2), Multi_pinfo_pilot_coords[gr_screen.res][1], place_text);
605 // otherwise blit the bitmap
607 gr_set_bitmap(Mp_pilot.bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
609 // get width and heigh
610 bm_get_info(Mp_pilot.bitmap, &w, &h, NULL, NULL, NULL, NULL);
612 gr_bitmap(Multi_pinfo_pilot_coords[gr_screen.res][0] + ((Multi_pinfo_pilot_coords[gr_screen.res][2] - w)/2),
613 Multi_pinfo_pilot_coords[gr_screen.res][1] + ((Multi_pinfo_pilot_coords[gr_screen.res][3] - h)/2));
614 // g3_draw_2d_poly_bitmap(Multi_pinfo_pilot_coords[gr_screen.res][0], Multi_pinfo_pilot_coords[gr_screen.res][1], Multi_pinfo_pilot_coords[gr_screen.res][2], Multi_pinfo_pilot_coords[gr_screen.res][3]);
618 // blit the pilot squadron logo
619 void multi_pinfo_blit_squadron_logo()
621 #ifndef MAKE_FS1 // no squads in FS1
622 char place_text[100];
624 player *p = Multi_pinfo_popup_player->player;
626 // if we don't have a bitmap handle, blit a placeholder
627 if(Mp_squad.bitmap == -1){
628 gr_set_color_fast(&Color_normal);
630 // if there is no image
631 if(strlen(p->squad_filename) <= 0){
632 SDL_strlcpy(place_text, XSTR("No/Invalid Image", 1053), SDL_arraysize(place_text));
634 // if the image is xferring
635 else if(multi_xfer_lookup(p->squad_filename)){
636 SDL_strlcpy(place_text, XSTR("Image Transferring", 691), SDL_arraysize(place_text));
638 // if we're not accepting images
639 else if(!(Net_player->p_info.options.flags & MLO_FLAG_ACCEPT_PIX) || !(Netgame.options.flags & MSO_FLAG_ACCEPT_PIX)){
640 SDL_strlcpy(place_text, XSTR("No Image", 692), SDL_arraysize(place_text));
644 SDL_strlcpy(place_text, XSTR("Waiting", 690), SDL_arraysize(place_text));
648 gr_get_string_size(&w, NULL, place_text);
649 gr_string(Multi_pinfo_squad_coords[gr_screen.res][0] + ((Multi_pinfo_squad_coords[gr_screen.res][2] - w)/2), Multi_pinfo_squad_coords[gr_screen.res][1], place_text);
651 // otherwise blit the bitmap
653 gr_set_bitmap(Mp_squad.bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
654 // gr_bitmap(MPI_SQUAD_X, MPI_SQUAD_Y);
656 // get width and heigh
657 bm_get_info(Mp_squad.bitmap, &w, &h, NULL, NULL, NULL, NULL);
659 gr_bitmap(Multi_pinfo_squad_coords[gr_screen.res][0] + ((Multi_pinfo_squad_coords[gr_screen.res][2] - w)/2),
660 Multi_pinfo_squad_coords[gr_screen.res][1] + ((Multi_pinfo_squad_coords[gr_screen.res][3] - h)/2));
661 // g3_draw_2d_poly_bitmap(Multi_pinfo_squad_coords[gr_screen.res][0], Multi_pinfo_squad_coords[gr_screen.res][1], Multi_pinfo_squad_coords[gr_screen.res][2], Multi_pinfo_squad_coords[gr_screen.res][3]);
666 // blit the player statistics
667 void multi_pinfo_blit_player_stats()
671 // blit the player's callsign and "all time stats"
672 gr_set_color_fast(&Color_bright);
673 gr_string(Multi_pinfo_stats_area_coords[gr_screen.res][0], Multi_pinfo_stats_area_coords[gr_screen.res][1], Multi_pinfo_popup_player->player->callsign);
674 gr_string(Multi_pinfo_stats_x[gr_screen.res], Multi_pinfo_stats_area_coords[gr_screen.res][1], XSTR("All Time Stats", 128));
676 gr_set_color_fast(&Color_normal);
678 // blit all the labels
679 y_start = Multi_pinfo_stats_area_coords[gr_screen.res][1] + 15;
680 for(idx=0;idx<MULTI_PINFO_NUM_STATS_LABELS;idx++){
681 gr_string(Multi_pinfo_stats_area_coords[gr_screen.res][0], y_start, Multi_pinfo_stats_labels[idx]);
682 y_start += Multi_pinfo_stats_label_offsets[idx];
685 // blit all the stats values themselves
686 y_start = Multi_pinfo_stats_area_coords[gr_screen.res][1] + 15;
687 for(idx=0;idx<MULTI_PINFO_NUM_STATS_LABELS;idx++){
688 gr_string(Multi_pinfo_stats_x[gr_screen.res], y_start, Multi_pinfo_stats_vals[idx]);
689 y_start += Multi_pinfo_stats_label_offsets[idx];
693 // check for button presses
694 void multi_pinfo_popup_check_buttons()
698 // check for all buttons
699 for(idx=0;idx<MULTI_PINFO_NUM_BUTTONS;idx++){
700 if(Multi_pinfo_buttons[gr_screen.res][idx].button.pressed()){
701 multi_pinfo_popup_button_pressed(idx);
707 // act on a button press
708 void multi_pinfo_popup_button_pressed(int n)
714 Multi_pinfo_popup_done = 1;
718 gamesnd_play_iface(SND_USER_SELECT);
719 multi_pinfo_do_medals();
722 case MPI_SCROLL_STATS_UP:
723 swap = multi_pinfo_get_prev_player(Multi_pinfo_popup_player);
725 gamesnd_play_iface(SND_USER_SELECT);
726 multi_pinfo_reset_player(swap);
728 gamesnd_play_iface(SND_GENERAL_FAIL);
732 case MPI_SCROLL_STATS_DOWN:
733 swap = multi_pinfo_get_next_player(Multi_pinfo_popup_player);
735 gamesnd_play_iface(SND_USER_SELECT);
736 multi_pinfo_reset_player(swap);
738 gamesnd_play_iface(SND_GENERAL_FAIL);
743 gamesnd_play_iface(SND_GENERAL_FAIL);
748 // display the medals screen for this player
749 void multi_pinfo_do_medals()
752 game_feature_not_in_demo_popup();
756 // initialize the medals screen
757 medal_main_init(Multi_pinfo_popup_player->player,MM_POPUP);
759 // run the medals screen until it says that it should be closed
761 // set frametime and run common functions
762 game_set_frametime(-1);
763 game_do_state_common(gameseq_get_state());
765 // run the medals screen
766 ret_code = medal_main_do();
767 } while(ret_code && !Multi_pinfo_popup_done);
769 // close the medals screen down
772 // restore the proper palette
773 multi_pinfo_set_palette();
777 // load up and use the proper palette
778 void multi_pinfo_set_palette()
782 // build the stats value strings for this player
783 void multi_pinfo_build_stats()
786 // int fighter_kills,other_kills;
787 scoring_struct *sc = &Multi_pinfo_popup_player->player->stats;
789 // build alltime fighter and non-fighter kills
793 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
794 if(sc->kills[idx] > 0){
795 if(Ship_info[idx].flags & SIF_FIGHTER){
796 fighter_kills += sc->kills[idx];
798 other_kills += sc->kills[idx];
803 SDL_snprintf(Multi_pinfo_stats_vals[MPI_FIGHTER_KILLS], MAX_LABEL_TEXT, "%d", sc->kill_count);
805 // sprintf(Multi_pinfo_stats_vals[MPI_OTHER_KILLS],"%d",other_kills);
808 SDL_snprintf(Multi_pinfo_stats_vals[MPI_MISSIONS_FLOWN], MAX_LABEL_TEXT, "%d", (int)sc->missions_flown);
811 game_format_time(fl2f((float)sc->flight_time), Multi_pinfo_stats_vals[MPI_FLIGHT_TIME], MAX_LABEL_TEXT);
814 if(sc->last_flown == 0){
815 SDL_strlcpy(Multi_pinfo_stats_vals[MPI_LAST_FLOWN], XSTR("No missions flown", 693), MAX_LABEL_TEXT);
817 time_t last_flown_tmp = 0;
818 tm *tmr = gmtime(&last_flown_tmp);
819 sc->last_flown = (fs_time_t)last_flown_tmp;
821 strftime(Multi_pinfo_stats_vals[MPI_LAST_FLOWN],MAX_LABEL_TEXT,"%m/%d/%y %H:%M",tmr);
823 SDL_strlcpy(Multi_pinfo_stats_vals[MPI_LAST_FLOWN], "", MAX_LABEL_TEXT);
828 SDL_strlcpy(Multi_pinfo_stats_vals[MPI_RANK], Ranks[sc->rank].name, MAX_LABEL_TEXT);
830 // primary shots fired
831 SDL_snprintf(Multi_pinfo_stats_vals[MPI_PSHOTS_FIRED], MAX_LABEL_TEXT, "%d", sc->p_shots_fired);
834 // sprintf(Multi_pinfo_stats_vals[MPI_PSHOTS_HIT],"%d",sc->p_shots_hit);
837 if (sc->p_shots_fired > 0) {
838 SDL_snprintf(Multi_pinfo_stats_vals[MPI_PSHOTS_PCT], MAX_LABEL_TEXT, "%d%%", (int)(100.0f * ((float)sc->p_shots_hit / (float)sc->p_shots_fired)));
840 SDL_strlcpy(Multi_pinfo_stats_vals[MPI_PSHOTS_PCT], "0%", MAX_LABEL_TEXT);
842 // primary shots fired
843 SDL_snprintf(Multi_pinfo_stats_vals[MPI_SSHOTS_FIRED], MAX_LABEL_TEXT, "%d", sc->s_shots_fired);
846 // sprintf(Multi_pinfo_stats_vals[MPI_SSHOTS_HIT],"%d",sc->s_shots_hit);
849 if (sc->s_shots_fired > 0) {
850 SDL_snprintf(Multi_pinfo_stats_vals[MPI_SSHOTS_PCT], MAX_LABEL_TEXT, "%d%%", (int)(100.0f * ((float)sc->s_shots_hit / (float)sc->s_shots_fired)));
852 SDL_strlcpy(Multi_pinfo_stats_vals[MPI_SSHOTS_PCT], "0%", MAX_LABEL_TEXT);
856 // if the pilot's image was currently loading when we started the popup, load it up now if its finished
857 void multi_pinfo_maybe_reload_pic(np_bitmap *b)
859 // if the bitmap is valid, do nothing
864 // if the local player is not accepting pix or the netgame is not accepting pix, bail here
865 if(!(Net_player->p_info.options.flags & MLO_FLAG_ACCEPT_PIX) || !(Netgame.options.flags & MSO_FLAG_ACCEPT_PIX)){
869 // if the bitmap filename is bogus
870 if(strlen(b->filename) <= 0){
875 b->bitmap = bm_load_duplicate(b->filename);
878 // attempt to validate a bitmap (ie, return whether its displayable or not)
880 int multi_pinfo_validate_bitmap(int bitmap)
884 // if the bitmap handle is invalid false
889 // get the bitmap info
892 bm_get_info(bitmap,&w,&h);
895 if((w != MPI_IMAGE_W) || (h != MPI_IMAGE_H)){
904 // is the pilot info popup currently active?
905 int multi_pinfo_popup_active()
907 return Multi_pinfo_popup_running;
910 // kill the currently active popup (if any)
911 void multi_pinfo_popup_kill()
913 // we're done, byatch
914 Multi_pinfo_popup_done = 1;
917 // reset the player infomation for this popup
918 void multi_pinfo_reset_player(net_player *np)
921 Multi_pinfo_popup_player = np;
923 // unload any old image data if necessary
924 SDL_strlcpy(Mp_pilot.filename, "", SDL_arraysize(Mp_pilot.filename));
925 if(Mp_pilot.bitmap != -1){
926 bm_release(Mp_pilot.bitmap);
927 Mp_pilot.bitmap = -1;
929 SDL_strlcpy(Mp_squad.filename, "", SDL_arraysize(Mp_squad.filename));
930 if(Mp_squad.bitmap != -1){
931 bm_release(Mp_squad.bitmap);
932 Mp_squad.bitmap = -1;
935 // try and load pilot pic/squad logo
936 if(strlen(np->player->image_filename) > 0){
937 SDL_strlcpy(Mp_pilot.filename, np->player->image_filename, SDL_arraysize(Mp_pilot.filename));
938 Mp_pilot.bitmap = bm_load_duplicate(Mp_pilot.filename);
940 if(strlen(np->player->squad_filename) > 0){
941 SDL_strlcpy(Mp_squad.filename, np->player->squad_filename, SDL_arraysize(Mp_squad.filename));
942 Mp_squad.bitmap = bm_load_duplicate(Mp_squad.filename);
945 // build the stats value strings for this player
946 multi_pinfo_build_stats();
949 // lookup the "previous" player in the netplayer list, return null if not found
950 net_player *multi_pinfo_get_prev_player(net_player *np)
955 // get the starting index to look from
956 start_index = NET_PLAYER_INDEX(np);
959 for(idx=start_index-1; idx>=0; idx--){
960 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){
961 return &Net_players[idx];
969 // lookup the "next" player in the netplayer list, return null if not found
970 net_player *multi_pinfo_get_next_player(net_player *np)
975 // get the starting index to look from
976 start_index = NET_PLAYER_INDEX(np);
977 if(start_index < (MAX_PLAYERS - 1)){
979 for(idx=start_index+1; idx<MAX_PLAYERS; idx++){
980 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){
981 return &Net_players[idx];