2 * $Logfile: /Freespace2/code/Network/multi_pinfo.cpp $
8 * Revision 1.2 2002/05/07 03:16:47 theoddone33
9 * The Great Newline Fix
11 * Revision 1.1.1.1 2002/05/03 03:28:10 root
15 * 15 9/10/99 9:44p Dave
16 * Bumped version # up. Make server reliable connects not have such a huge
19 * 14 8/30/99 5:01p Dave
20 * Made d3d do less state changing in the nebula. Use new chat server for
23 * 13 8/22/99 5:53p Dave
24 * Scoring fixes. Added self destruct key. Put callsigns in the logfile
25 * instead of ship designations for multiplayer players.
27 * 12 8/03/99 11:43a Dave
28 * Don't allow medals button in demo.
30 * 11 7/26/99 11:14a Andsager
31 * Disable medals in demo multiplayer
33 * 10 6/16/99 4:06p Dave
34 * New pilot info popup. Added new draw-bitmap-as-poly function.
36 * 9 1/30/99 1:29a Dave
37 * Fixed nebula thumbnail problem. Full support for 1024x768 choose pilot
38 * screen. Fixed beam weapon death messages.
40 * 8 1/14/99 6:06p Dave
41 * 100% full squad logo support for single player and multiplayer.
43 * 7 1/12/99 4:07a Dave
44 * Put in barracks code support for selecting squad logos. Properly
45 * distribute squad logos in a multiplayer game.
47 * 6 12/14/98 12:13p Dave
48 * Spiffed up xfer system a bit. Put in support for squad logo file xfer.
51 * 5 11/30/98 1:07p Dave
52 * 16 bit conversion, first run.
54 * 4 11/05/98 4:18p Dave
55 * First run nebula support. Beefed up localization a bit. Removed all
56 * conditional compiles for foreign versions. Modified mission file
59 * 3 10/13/98 9:29a Dave
60 * Started neatening up freespace.h. Many variables renamed and
61 * reorganized. Added AlphaColors.[h,cpp]
63 * 2 10/07/98 10:53a Dave
66 * 1 10/07/98 10:50a Dave
75 #include "freespace.h"
76 #include "gamesequence.h"
82 #include "multi_xfer.h"
83 #include "multi_pinfo.h"
84 #include "alphacolors.h"
88 // ---------------------------------------------------------------------------------------
89 // MULTI PLAYER INFO DEFINES/VARS
94 #define MULTI_PINFO_NUM_BUTTONS 4
97 char *Multi_pinfo_bitmap_name[GR_NUM_RESOLUTIONS] = {
101 char *Multi_pinfo_bitmap_mask[GR_NUM_RESOLUTIONS] = {
107 #define MPI_SCROLL_STATS_UP 0
108 #define MPI_SCROLL_STATS_DOWN 1
112 // pilot image area defs
113 int Multi_pinfo_pilot_coords[GR_NUM_RESOLUTIONS][4] = {
121 int Multi_pinfo_squad_coords[GR_NUM_RESOLUTIONS][4] = {
131 typedef struct np_bitmap {
132 int bitmap; // bitmap id
133 char filename[MAX_FILENAME_LEN]; // filename
135 np_bitmap Mp_pilot; // pilot pic
136 np_bitmap Mp_squad; // squad logo
138 UI_WINDOW Multi_pinfo_window; // the window object for the join screen
139 UI_BUTTON Multi_pinfo_select_button; // for selecting list items
140 int Multi_pinfo_bitmap; // the background bitmap
141 ui_button_info Multi_pinfo_buttons[GR_NUM_RESOLUTIONS][MULTI_PINFO_NUM_BUTTONS] = {
143 ui_button_info("PIB_00", 617, 256, -1, -1, 0),
144 ui_button_info("PIB_01", 617, 298, -1, -1, 1),
145 ui_button_info("PIB_02", 172, 322, -1, -1, 2),
146 ui_button_info("PIB_03", 219, 332, 217, 318, 3)
149 ui_button_info("2_PIB_00", 988, 410, -1, -1, 0),
150 ui_button_info("2_PIB_01", 988, 477, -1, -1, 1),
151 ui_button_info("2_PIB_02", 276, 516, -1, -1, 2),
152 ui_button_info("2_PIB_03", 350, 532, 348, 510, 3)
156 #define MULTI_PINFO_NUM_TEXT 1
157 UI_XSTR Multi_pinfo_text[GR_NUM_RESOLUTIONS][MULTI_PINFO_NUM_TEXT] = {
159 { "Close", 428, 217, 318, UI_XSTR_COLOR_PINK, -1, &Multi_pinfo_buttons[0][MPI_EXIT].button },
162 { "Close", 428, 348, 510, UI_XSTR_COLOR_PINK, -1, &Multi_pinfo_buttons[1][MPI_EXIT].button },
169 #define MULTI_PINFO_NUM_STATS_LABELS 9
171 #define MPI_MISSIONS_FLOWN 1
172 #define MPI_FLIGHT_TIME 2
173 #define MPI_LAST_FLOWN 3
174 #define MPI_FIGHTER_KILLS 4
175 // #define MPI_OTHER_KILLS 5
176 #define MPI_PSHOTS_FIRED 5
177 //#define MPI_PSHOTS_HIT 6
178 #define MPI_PSHOTS_PCT 6
179 #define MPI_SSHOTS_FIRED 7
180 // #define MPI_SSHOTS_HIT 10
181 #define MPI_SSHOTS_PCT 8
183 char *Multi_pinfo_stats_labels[MULTI_PINFO_NUM_STATS_LABELS];
185 #define MAX_LABEL_TEXT 50
186 char Multi_pinfo_stats_vals[MULTI_PINFO_NUM_STATS_LABELS][MAX_LABEL_TEXT];
187 int Multi_pinfo_stats_label_offsets[MULTI_PINFO_NUM_STATS_LABELS] = {
188 20,10,10,20,20,10,20,10,10,
192 int Multi_pinfo_stats_area_coords[GR_NUM_RESOLUTIONS][4] = {
200 int Multi_pinfo_stats_x[GR_NUM_RESOLUTIONS] = {
205 // is the popup already running
206 int Multi_pinfo_popup_running = 0;
208 // background bitmap to be blitted
209 int Multi_pinfo_screen_save = -1;
211 // flag indicating if the popup has gotten messed up somewhere and should bail
212 int Multi_pinfo_popup_error = 0;
214 // flag indicating if the popup should be done
215 int Multi_pinfo_popup_done = 0;
217 // player this popup is being used for
218 net_player *Multi_pinfo_popup_player = NULL;
221 extern shader Grey_shader;
223 // hardware textures backup
224 int Multi_pinfo_hardware_texture_backup;
227 // ---------------------------------------------------------------------------------------
228 // MULTI PLAYER INFO FORWARD DECLARATIONS
231 // initialize all popup details (graphics, etc)
232 void multi_pinfo_popup_init(net_player *pl);
234 // run the popup in a tight loop (no states)
235 void multi_pinfo_popup_do();
238 void multi_pinfo_popup_close();
240 // blit the pilot image
241 void multi_pinfo_blit_pilot_image();
243 // blit the pilot squadron logo
244 void multi_pinfo_blit_squadron_logo();
246 // blit the player statistics
247 void multi_pinfo_blit_player_stats();
249 // check for button presses
250 void multi_pinfo_popup_check_buttons();
252 // act on a button press
253 void multi_pinfo_popup_button_pressed(int n);
255 // display the medals screen for this player
256 void multi_pinfo_do_medals();
258 // load up and use the proper palette
259 void multi_pinfo_set_palette();
261 // build the stats value strings for this player
262 void multi_pinfo_build_stats();
264 // if the pilot's image was currently loading when we started the popup, load it up now if its finished
265 void multi_pinfo_maybe_reload_pic(np_bitmap *b);
267 // reset the player infomation for this popup
268 void multi_pinfo_reset_player(net_player *np);
270 // lookup the "previous" player in the netplayer list, return null if not found
271 net_player *multi_pinfo_get_prev_player(net_player *np);
273 // lookup the "next" player in the netplayer list, return null if not found
274 net_player *multi_pinfo_get_next_player(net_player *np);
277 // ---------------------------------------------------------------------------------------
278 // MULTI PLAYER INFO FUNCTIONS
281 // fire up the player info popup, select first available pilot if np == NULL
282 void multi_pinfo_popup(net_player *np)
284 // if the popup is already running, don't do anything
285 if(Multi_pinfo_popup_running){
289 // set the player for informational purposes
292 // play the popup appear sound
293 gamesnd_play_iface(SND_POPUP_APPEAR);
295 // initialize the popup
296 multi_pinfo_popup_init(np);
298 // mark the popup as running
299 Multi_pinfo_popup_running = 1;
302 multi_pinfo_popup_do();
305 multi_pinfo_popup_close();
307 // play the popup disappear sound
308 gamesnd_play_iface(SND_POPUP_DISAPPEAR);
311 // notify the popup that a player has left
312 void multi_pinfo_notify_drop(net_player *np)
316 // if we're no active, bail
317 if(!Multi_pinfo_popup_running){
321 // if this is not the player we're currently displaying, bail
322 if(np != Multi_pinfo_popup_player){
326 // otherwise we need to switch to someone else
327 reset = multi_pinfo_get_prev_player(np);
329 multi_pinfo_reset_player(reset);
332 reset = multi_pinfo_get_next_player(np);
334 multi_pinfo_reset_player(reset);
338 // bail, since there's no one else
340 Multi_pinfo_popup_done = 1;
344 // ---------------------------------------------------------------------------------------
345 // MULTI PLAYER INFO FORWARD DEFINITIONS
348 // initialize all popup details (graphics, etc)
349 void multi_pinfo_popup_init(net_player *np)
353 // no errors to start with
354 Multi_pinfo_popup_error = 0;
357 Multi_pinfo_popup_done = 0;
359 // store the background as it currently is
360 Multi_pinfo_screen_save = gr_save_screen();
361 if(Multi_pinfo_screen_save == -1){
362 Multi_pinfo_popup_error = 1;
366 // create the interface window
367 Multi_pinfo_window.create(0,0,gr_screen.max_w,gr_screen.max_h,0);
368 Multi_pinfo_window.set_mask_bmap(Multi_pinfo_bitmap_mask[gr_screen.res]);
370 // load the background bitmap
371 Multi_pinfo_bitmap = bm_load(Multi_pinfo_bitmap_name[gr_screen.res]);
372 if(Multi_pinfo_bitmap < 0){
373 Multi_pinfo_popup_error = 1;
377 // backup hardware textures setting and bash to max
378 Multi_pinfo_hardware_texture_backup = Detail.hardware_textures;
379 Detail.hardware_textures = MAX_DETAIL_LEVEL;
382 Mp_pilot.bitmap = -1;
383 strcpy(Mp_pilot.filename, "");
384 Mp_squad.bitmap = -1;
385 strcpy(Mp_squad.filename, "");
387 // set the player status
388 multi_pinfo_reset_player(np);
390 // create the interface buttons
391 for(idx=0;idx<MULTI_PINFO_NUM_BUTTONS;idx++){
393 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);
395 // set the sound to play when highlighted
396 Multi_pinfo_buttons[gr_screen.res][idx].button.set_highlight_action(common_play_highlight_sound);
398 // set the ani for the button
399 Multi_pinfo_buttons[gr_screen.res][idx].button.set_bmaps(Multi_pinfo_buttons[gr_screen.res][idx].filename);
402 Multi_pinfo_buttons[gr_screen.res][idx].button.link_hotspot(Multi_pinfo_buttons[gr_screen.res][idx].hotspot);
406 for(idx=0; idx<MULTI_PINFO_NUM_TEXT; idx++){
407 Multi_pinfo_window.add_XSTR(&Multi_pinfo_text[gr_screen.res][idx]);
410 // disable medals button for the demo
412 Multi_pinfo_buttons[gr_screen.res][MPI_MEDALS].button.hide();
413 Multi_pinfo_buttons[gr_screen.res][MPI_MEDALS].button.disable();
416 // initialize strings
417 Multi_pinfo_stats_labels[0] = strdup(XSTR("Rank", 1007));
418 Multi_pinfo_stats_labels[1] = strdup(XSTR("Missions Flown", 1008));
419 Multi_pinfo_stats_labels[2] = strdup(XSTR("Flight Time", 1009));
420 Multi_pinfo_stats_labels[3] = strdup(XSTR("Last Flown",1010));
421 Multi_pinfo_stats_labels[4] = strdup(XSTR("Total Kills", 115));
422 Multi_pinfo_stats_labels[5] = strdup(XSTR("Primary Shots Fired", 1012));
423 Multi_pinfo_stats_labels[6] = strdup(XSTR("Primary Hit %", 1013));
424 Multi_pinfo_stats_labels[7] = strdup(XSTR("Secondary Shots Fired", 1014));
425 Multi_pinfo_stats_labels[8] = strdup(XSTR("Secondary Hit %", 1015));
428 // run the popup in a tight loop (no states)
429 void multi_pinfo_popup_do()
433 // if there was an error in initialization, return immediately
434 if(Multi_pinfo_popup_error){
439 while(!Multi_pinfo_popup_done){
440 multi_pinfo_maybe_reload_pic(&Mp_pilot);
441 multi_pinfo_maybe_reload_pic(&Mp_squad);
443 // process the window
444 k = Multi_pinfo_window.process();
447 Multi_pinfo_popup_done = 1;
451 // check button presses
452 multi_pinfo_popup_check_buttons();
454 // set frametime and run background stuff
455 game_set_frametime(-1);
456 game_do_state_common(gameseq_get_state());
458 // draw the background bitmap and the ui window over it
459 Assert(Multi_pinfo_screen_save != -1);
461 gr_restore_screen(Multi_pinfo_screen_save);
464 gr_set_shader(&Grey_shader);
465 gr_shade(0,0,gr_screen.clip_width, gr_screen.clip_height);
467 // draw the background bitmap
468 gr_set_bitmap(Multi_pinfo_bitmap);
471 // blit the selected pilot image
472 multi_pinfo_blit_pilot_image();
474 // blit the squadron logo
475 multi_pinfo_blit_squadron_logo();
477 // blit the player statistics
478 multi_pinfo_blit_player_stats();
480 // draw the ui window and flip
481 Multi_pinfo_window.draw();
487 void multi_pinfo_popup_close()
491 // unload any bitmaps
492 if(Multi_pinfo_bitmap != -1){
493 bm_release(Multi_pinfo_bitmap);
496 // free the background screen if possible
497 if(Multi_pinfo_screen_save >= 0){
498 gr_free_screen(Multi_pinfo_screen_save);
501 // release the pilot/squad images
502 if(Mp_pilot.bitmap != -1){
503 bm_release(Mp_pilot.bitmap);
505 if(Mp_squad.bitmap != -1){
506 bm_release(Mp_squad.bitmap);
510 for(idx=0; idx<MULTI_PINFO_NUM_STATS_LABELS; idx++){
511 if(Multi_pinfo_stats_labels[idx] != NULL){
512 free(Multi_pinfo_stats_labels[idx]);
513 Multi_pinfo_stats_labels[idx] = NULL;
517 // unset the player handle
518 Multi_pinfo_popup_player = NULL;
520 // mark the popup as not running
521 Multi_pinfo_popup_running = 0;
523 // destroy the UI_WINDOW
524 Multi_pinfo_window.destroy();
526 // restore hardware textures detail level
527 Detail.hardware_textures = Multi_pinfo_hardware_texture_backup;
530 // blit the pilot image
531 void multi_pinfo_blit_pilot_image()
533 char place_text[100];
536 // if we don't have a bitmap handle, blit a placeholder
537 if(Mp_pilot.bitmap == -1){
538 gr_set_color_fast(&Color_normal);
540 // if there is no image
541 if(strlen(Mp_pilot.filename) <= 0){
542 strcpy(place_text,XSTR("No/Invalid Image", 1053));
544 // if the image is xferring
545 else if(multi_xfer_lookup(Mp_pilot.filename)){
546 strcpy(place_text,XSTR("Image Transferring", 691));
548 // if we're not accepting images
549 else if(!(Net_player->p_info.options.flags & MLO_FLAG_ACCEPT_PIX) || !(Netgame.options.flags & MSO_FLAG_ACCEPT_PIX)){
550 strcpy(place_text,XSTR("No Image", 692));
554 strcpy(place_text,XSTR("Waiting", 690));
558 gr_get_string_size(&w,NULL,place_text);
559 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);
561 // otherwise blit the bitmap
563 gr_set_bitmap(Mp_pilot.bitmap);
565 // get width and heigh
567 bm_get_info(Mp_pilot.bitmap, &w, &h, NULL, NULL, NULL, NULL);
569 gr_bitmap(Multi_pinfo_pilot_coords[gr_screen.res][0] + ((Multi_pinfo_pilot_coords[gr_screen.res][2] - w)/2),
570 Multi_pinfo_pilot_coords[gr_screen.res][1] + ((Multi_pinfo_pilot_coords[gr_screen.res][3] - h)/2));
571 // 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]);
575 // blit the pilot squadron logo
576 void multi_pinfo_blit_squadron_logo()
578 char place_text[100];
580 player *p = Multi_pinfo_popup_player->player;
582 // if we don't have a bitmap handle, blit a placeholder
583 if(Mp_squad.bitmap == -1){
584 gr_set_color_fast(&Color_normal);
586 // if there is no image
587 if(strlen(p->squad_filename) <= 0){
588 strcpy(place_text,XSTR("No/Invalid Image", 1053));
590 // if the image is xferring
591 else if(multi_xfer_lookup(p->squad_filename)){
592 strcpy(place_text,XSTR("Image Transferring", 691));
594 // if we're not accepting images
595 else if(!(Net_player->p_info.options.flags & MLO_FLAG_ACCEPT_PIX) || !(Netgame.options.flags & MSO_FLAG_ACCEPT_PIX)){
596 strcpy(place_text,XSTR("No Image", 692));
600 strcpy(place_text,XSTR("Waiting", 690));
604 gr_get_string_size(&w, NULL, place_text);
605 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);
607 // otherwise blit the bitmap
609 gr_set_bitmap(Mp_squad.bitmap);
610 // gr_bitmap(MPI_SQUAD_X, MPI_SQUAD_Y);
612 // get width and heigh
614 bm_get_info(Mp_squad.bitmap, &w, &h, NULL, NULL, NULL, NULL);
616 gr_bitmap(Multi_pinfo_squad_coords[gr_screen.res][0] + ((Multi_pinfo_squad_coords[gr_screen.res][2] - w)/2),
617 Multi_pinfo_squad_coords[gr_screen.res][1] + ((Multi_pinfo_squad_coords[gr_screen.res][3] - h)/2));
618 // 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]);
622 // blit the player statistics
623 void multi_pinfo_blit_player_stats()
627 // blit the player's callsign and "all time stats"
628 gr_set_color_fast(&Color_bright);
629 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);
630 gr_string(Multi_pinfo_stats_x[gr_screen.res], Multi_pinfo_stats_area_coords[gr_screen.res][1], XSTR("All Time Stats", 128));
632 gr_set_color_fast(&Color_normal);
634 // blit all the labels
635 y_start = Multi_pinfo_stats_area_coords[gr_screen.res][1] + 15;
636 for(idx=0;idx<MULTI_PINFO_NUM_STATS_LABELS;idx++){
637 gr_string(Multi_pinfo_stats_area_coords[gr_screen.res][0], y_start, Multi_pinfo_stats_labels[idx]);
638 y_start += Multi_pinfo_stats_label_offsets[idx];
641 // blit all the stats values themselves
642 y_start = Multi_pinfo_stats_area_coords[gr_screen.res][1] + 15;
643 for(idx=0;idx<MULTI_PINFO_NUM_STATS_LABELS;idx++){
644 gr_string(Multi_pinfo_stats_x[gr_screen.res], y_start, Multi_pinfo_stats_vals[idx]);
645 y_start += Multi_pinfo_stats_label_offsets[idx];
649 // check for button presses
650 void multi_pinfo_popup_check_buttons()
654 // check for all buttons
655 for(idx=0;idx<MULTI_PINFO_NUM_BUTTONS;idx++){
656 if(Multi_pinfo_buttons[gr_screen.res][idx].button.pressed()){
657 multi_pinfo_popup_button_pressed(idx);
663 // act on a button press
664 void multi_pinfo_popup_button_pressed(int n)
670 Multi_pinfo_popup_done = 1;
674 gamesnd_play_iface(SND_USER_SELECT);
675 multi_pinfo_do_medals();
678 case MPI_SCROLL_STATS_UP:
679 swap = multi_pinfo_get_prev_player(Multi_pinfo_popup_player);
681 gamesnd_play_iface(SND_USER_SELECT);
682 multi_pinfo_reset_player(swap);
684 gamesnd_play_iface(SND_GENERAL_FAIL);
688 case MPI_SCROLL_STATS_DOWN:
689 swap = multi_pinfo_get_next_player(Multi_pinfo_popup_player);
691 gamesnd_play_iface(SND_USER_SELECT);
692 multi_pinfo_reset_player(swap);
694 gamesnd_play_iface(SND_GENERAL_FAIL);
699 gamesnd_play_iface(SND_GENERAL_FAIL);
704 // display the medals screen for this player
705 void multi_pinfo_do_medals()
708 game_feature_not_in_demo_popup();
712 // initialize the medals screen
713 medal_main_init(Multi_pinfo_popup_player->player,MM_POPUP);
715 // run the medals screen until it says that it should be closed
717 // set frametime and run common functions
718 game_set_frametime(-1);
719 game_do_state_common(gameseq_get_state());
721 // run the medals screen
722 ret_code = medal_main_do();
723 } while(ret_code && !Multi_pinfo_popup_done);
725 // close the medals screen down
728 // restore the proper palette
729 multi_pinfo_set_palette();
733 // load up and use the proper palette
734 void multi_pinfo_set_palette()
736 #ifndef HARDWARE_ONLY
737 palette_use_bm_palette(Multi_pinfo_bitmap);
741 // build the stats value strings for this player
742 void multi_pinfo_build_stats()
745 // int fighter_kills,other_kills;
746 scoring_struct *sc = &Multi_pinfo_popup_player->player->stats;
748 // build alltime fighter and non-fighter kills
752 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
753 if(sc->kills[idx] > 0){
754 if(Ship_info[idx].flags & SIF_FIGHTER){
755 fighter_kills += sc->kills[idx];
757 other_kills += sc->kills[idx];
762 sprintf(Multi_pinfo_stats_vals[MPI_FIGHTER_KILLS], "%d", sc->kill_count);
764 // sprintf(Multi_pinfo_stats_vals[MPI_OTHER_KILLS],"%d",other_kills);
767 sprintf(Multi_pinfo_stats_vals[MPI_MISSIONS_FLOWN],"%d",(int)sc->missions_flown);
770 game_format_time(fl2f((float)sc->flight_time),Multi_pinfo_stats_vals[MPI_FLIGHT_TIME]);
773 if(sc->last_flown == 0){
774 strcpy(Multi_pinfo_stats_vals[MPI_LAST_FLOWN],XSTR("No missions flown",693));
776 tm *tmr = gmtime(&sc->last_flown);
778 strftime(Multi_pinfo_stats_vals[MPI_LAST_FLOWN],MAX_LABEL_TEXT,"%m/%d/%y %H:%M",tmr);
780 strcpy(Multi_pinfo_stats_vals[MPI_LAST_FLOWN], "");
785 strcpy(Multi_pinfo_stats_vals[MPI_RANK],Ranks[sc->rank].name);
787 // primary shots fired
788 sprintf(Multi_pinfo_stats_vals[MPI_PSHOTS_FIRED],"%d",sc->p_shots_fired);
791 // sprintf(Multi_pinfo_stats_vals[MPI_PSHOTS_HIT],"%d",sc->p_shots_hit);
794 sprintf(Multi_pinfo_stats_vals[MPI_PSHOTS_PCT],"%d%%",(int)(100.0f * ((float)sc->p_shots_hit / (float)sc->p_shots_fired)));
795 // primary shots fired
796 sprintf(Multi_pinfo_stats_vals[MPI_SSHOTS_FIRED],"%d",sc->s_shots_fired);
799 // sprintf(Multi_pinfo_stats_vals[MPI_SSHOTS_HIT],"%d",sc->s_shots_hit);
802 sprintf(Multi_pinfo_stats_vals[MPI_SSHOTS_PCT],"%d%%",(int)(100.0f * ((float)sc->s_shots_hit / (float)sc->s_shots_fired)));
805 // if the pilot's image was currently loading when we started the popup, load it up now if its finished
806 void multi_pinfo_maybe_reload_pic(np_bitmap *b)
808 // if the bitmap is valid, do nothing
813 // if the local player is not accepting pix or the netgame is not accepting pix, bail here
814 if(!(Net_player->p_info.options.flags & MLO_FLAG_ACCEPT_PIX) || !(Netgame.options.flags & MSO_FLAG_ACCEPT_PIX)){
818 // if the bitmap filename is bogus
819 if(strlen(b->filename) <= 0){
824 b->bitmap = bm_load_duplicate(b->filename);
827 // attempt to validate a bitmap (ie, return whether its displayable or not)
829 int multi_pinfo_validate_bitmap(int bitmap)
833 // if the bitmap handle is invalid false
838 // get the bitmap info
841 bm_get_info(bitmap,&w,&h);
844 if((w != MPI_IMAGE_W) || (h != MPI_IMAGE_H)){
853 // is the pilot info popup currently active?
854 int multi_pinfo_popup_active()
856 return Multi_pinfo_popup_running;
859 // kill the currently active popup (if any)
860 void multi_pinfo_popup_kill()
862 // we're done, byatch
863 Multi_pinfo_popup_done = 1;
866 // reset the player infomation for this popup
867 void multi_pinfo_reset_player(net_player *np)
870 Multi_pinfo_popup_player = np;
872 // unload any old image data if necessary
873 strcpy(Mp_pilot.filename, "");
874 if(Mp_pilot.bitmap != -1){
875 bm_release(Mp_pilot.bitmap);
876 Mp_pilot.bitmap = -1;
878 strcpy(Mp_squad.filename, "");
879 if(Mp_squad.bitmap != -1){
880 bm_release(Mp_squad.bitmap);
881 Mp_squad.bitmap = -1;
884 // try and load pilot pic/squad logo
885 if(strlen(np->player->image_filename) >= 0){
886 strcpy(Mp_pilot.filename, np->player->image_filename);
887 Mp_pilot.bitmap = bm_load_duplicate(Mp_pilot.filename);
889 if(strlen(np->player->squad_filename) >= 0){
890 strcpy(Mp_squad.filename, np->player->squad_filename);
891 Mp_squad.bitmap = bm_load_duplicate(Mp_squad.filename);
894 // build the stats value strings for this player
895 multi_pinfo_build_stats();
898 // lookup the "previous" player in the netplayer list, return null if not found
899 net_player *multi_pinfo_get_prev_player(net_player *np)
904 // get the starting index to look from
905 start_index = NET_PLAYER_INDEX(np);
908 for(idx=start_index-1; idx>=0; idx--){
909 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){
910 return &Net_players[idx];
918 // lookup the "next" player in the netplayer list, return null if not found
919 net_player *multi_pinfo_get_next_player(net_player *np)
924 // get the starting index to look from
925 start_index = NET_PLAYER_INDEX(np);
926 if(start_index < (MAX_PLAYERS - 1)){
928 for(idx=start_index+1; idx<MAX_PLAYERS; idx++){
929 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){
930 return &Net_players[idx];