FS2_Open
Open source remastering of the Freespace 2 engine
multi_ingame.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include <limits.h> // this is need even when not building debug!!
14 
15 #include "globalincs/globals.h"
16 #include "object/object.h"
17 #include "ship/ship.h"
18 #include "weapon/weapon.h"
19 #include "network/multi.h"
20 #include "network/multiutil.h"
21 #include "network/multimsgs.h"
22 #include "network/multiui.h"
23 #include "mission/missionparse.h"
24 #include "freespace2/freespace.h"
26 #include "io/key.h"
27 #include "gamesnd/gamesnd.h"
28 #include "globalincs/linklist.h"
29 #include "network/multi_ingame.h"
31 #include "popup/popup.h"
32 #include "network/multi_observer.h"
33 #include "network/multi_xfer.h"
34 #include "network/multi_kick.h"
35 #include "menuui/mainhallmenu.h"
36 #include "stats/stats.h"
39 #include "network/multi_endgame.h"
40 #include "hud/hudshield.h"
41 #include "mission/missionhotkey.h"
42 #include "globalincs/alphacolors.h"
43 #include "io/timer.h"
44 #include "playerman/player.h"
45 #include "network/multi_log.h"
46 
47 
48 // --------------------------------------------------------------------------------------------------
49 // DAVE's BIGASS INGAME JOIN WARNING/DISCLAIMER
50 //
51 // Ingame joining is another delicate system. Although not as delicate as server transfer, it will
52 // help to take as many precautions as possible when handling ingame joins. Please be sure to follow
53 // all the same rules as explained in multi_strans.h
54 //
55 // --------------------------------------------------------------------------------------------------
56 
57 // --------------------------------------------------------------------------------------------------
58 // INGAME JOIN DESCRIPTION
59 //
60 // 1.) Joiner sends a JOIN packet to the server
61 // 2.) If the server accepts him, he receives an ACCEPT packet in return
62 // 3.) The client then moves into the INGAME_SYNC state to begin receiving data from the server
63 // 4.) The first thing he does on this screen is send his filesig packet to the server. At which
64 // point the server will either let him in or deny him. There are no file transfers ingame.
65 // 5.) The server calls multi_handle_ingame_joiners() once per frame, through multi_do_frame()
66 // 6.) After verifiying or kicking the player because of his file signature, the server tells the
67 // player to load the mission
68 // 7.) When the mission is loaded, the server, sends a netgame update to the client
69 // 8.) Without waiting, the server then begins sending data ship packets to the player
70 // 9.) Upon confirmation of receiving these packets, the server sends wing data packets
71 // 10.) Upon completion of this, the server sends respawn point packets
72 // 11.) Upon completion of this, the server sends a post briefing data block packet containing ship class and
73 // weapon information
74 // 12.) After this, the server sends a player settings packet (to all players for good measure)
75 // 13.) At this point, the server sends a jump into mission packet
76 // 14.) Upon receipt of this packet, the client moves into the ingame ship select state
77 // 15.) The first thing the client does in this state is load the mission data (textures, etc)
78 // 16.) The player is presented with a list of ships he can choose from. He selects one and sends
79 // an INGAME_SHIP_REQUEST to the server.
80 // 17.) The server checks to see if this request is acceptable and sends an INGAME_SHIP_REQUEST back
81 // with the appropriate data.
82 // 18.) If the client received an affirmative, he selects the ship and jumps into the mission, otherwise
83 // he removes it from the list and tries for another ship
84 // --------------------------------------------------------------------------------------------------
85 
86 
88 //LOCAL int Ingame_ships_to_delete[MAX_SHIPS];
89 
90 
91 // --------------------------------------------------------------------------------------------------
92 // INGAME JOIN FORWARD DECLARATIONS
93 //
94 
96 
99 
100 
101 
102 // --------------------------------------------------------------------------------------------------
103 // INGAME JOIN COMMON DEFINITIONS
104 //
105 
106 
107 // --------------------------------------------------------------------------------------------------
108 // INGAME JOIN SERVER FUNCTIONS
109 //
110 
111 // called on the server to process ingame joiners and move them through the motions of ingame joining
113 {
114  int idx;
115 
117 
118  // if my ingame joining flag isn't set, then don't do anything.
120  return;
121  }
122 
123  // traverse through all the players
124  for(idx = 0; idx<MAX_PLAYERS; idx++){
125  // only process ingame joiners
127  continue;
128  }
129 
130  // if we're waiting for players to receive files, then check on their status
131  if(Net_players[idx].s_info.ingame_join_flags & INGAME_JOIN_FLAG_FILE_XFER){
132  switch(multi_xfer_get_status(Net_players[idx].s_info.xfer_handle)){
133  // if it has successfully completed, set his ok flag
134  case MULTI_XFER_SUCCESS :
135  // set his ok flag
137 
138  // release the xfer instance handle
139  multi_xfer_release_handle(Net_players[idx].s_info.xfer_handle);
141  break;
142  // if it has failed or timed-out, kick the player
143  case MULTI_XFER_TIMEDOUT:
144  case MULTI_XFER_FAIL:
145  // release the xfer handle
146  multi_xfer_release_handle(Net_players[idx].s_info.xfer_handle);
148 
149  // kick the loser
151  break;
152  }
153  }
154 
155  // if the player has verified his file signature then send him the packet to load the mission and mark this down
156  if((Net_players[idx].flags & NETINFO_FLAG_MISSION_OK) && !(Net_players[idx].s_info.ingame_join_flags & INGAME_JOIN_FLAG_LOADING_MISSION)){
157  // send the netgame update here as well
160 
161  // send the packet and mark it down
164  }
165 
166  // once he has finished loading the mission, start sending him ship data packets and mark this down
167  if((Net_players[idx].state == NETPLAYER_STATE_MISSION_LOADED) && !(Net_players[idx].s_info.ingame_join_flags & INGAME_JOIN_FLAG_SENDING_SHIPS)){
168  int i;
169 
170  // send the packet and mark it down
171  for (i = 0; i < Num_teams; i++ ) {
173  send_wss_slots_data_packet(i, 1, &Net_players[idx], 0);
174  } else {
176  }
177  }
178 
179  // mark the netgame as a critical stage in ingame joining so that I don't evaluate mission event/
180  // goals, ship arrivals, etc.
182 
183  // send the packet and mark it down
186  }
187 
188  // once he has finished receiving the ship data, start sending him wing data and mark this down
189  /*
190  if((Net_players[idx].state == NETPLAYER_STATE_INGAME_SHIPS) && !(Net_players[idx].s_info.ingame_join_flags & INGAME_JOIN_FLAG_SENDING_WINGS)){
191  // setup the list of wings to send
192  Net_players[idx].s_info.wing_index = 0;
193  Net_players[idx].s_info.wing_index_backup = 0;
194 
195  // send the packet and mark it down
196  send_ingame_wings_packet(&Net_players[idx]);
197  Net_players[idx].s_info.ingame_join_flags |= INGAME_JOIN_FLAG_SENDING_WINGS;
198  }
199  */
200 
201  // once he has received the respawn packet, send him the player settings for all the players in the game and mark this down
202  if((Net_players[idx].state == NETPLAYER_STATE_INGAME_SHIPS) && !(Net_players[idx].s_info.ingame_join_flags & INGAME_JOIN_FLAG_SENDING_POST)){
203  // reset the critical ingame joining flag so that I as server, will start evaluating mission
204  // things again
206 
207  // send the packet and mark it down
210  } else {
212  }
214  }
215 
216  // once the settings have been received, send him the jump into mission packet and mark this down. now the joiner
217  // moves into the ship select state (ingame)
218  if((Net_players[idx].state == NETPLAYER_STATE_POST_DATA_ACK) && !(Net_players[idx].s_info.ingame_join_flags & INGAME_JOIN_FLAG_PICK_SHIP)){
219  // if this guy is an obsever, create his observer object and be done!
224  }
225 
226  // send the packet and mark it down
229  }
230 
231  // check to see if his timestamp for ship update (hull, shields, etc) has popped. If so, send some info and reset
232  if(timestamp_elapsed(Net_players[idx].s_info.last_full_update_time)){
233  // send the ships
235 
236  // reset the timestamp
238  }
239 
240  // once he has received the weapon state packet, send him the player settings for all the players in the game and mark this down
241  if(!(Net_players[idx].s_info.ingame_join_flags & INGAME_JOIN_FLAG_SENDING_SETS)){
242  // send the packet and mark it down
243  // this will update _ALL_ players in the game which is important
245  send_player_settings_packet( &Net_players[idx] ); // send directly so he gets the packet
246 
248  }
249  }
250 }
251 
252 // the final step for an ingame joining observer - create my observer object, unflag myself as joining and jump into mission
254 {
255  // create my local observer object
257 
258  // unflag myself as being an ingame joiner
260 
261  // set my state to be in-mission
264 
265  // jump into the game
267 }
268 
269 // --------------------------------------------------------------------------------------------------
270 // INGAME DATA SYNC SCREEN
271 //
272 
273 // mission sync screen init function for ingame joining
275 {
276  // if we couldn't get the file signature correctly. send some bogus values
278 
279  // everyone should re-initialize these
281 
282  // reset all sequencing info
284 
285  // send the file signature to the host for possible mission file transfer
288 
290 }
291 
292 // mission sync screen do function for ingame joining
294 {
295 }
296 
297 // mission sync screen do function for ingame joining
299 {
300 }
301 
302 
303 // --------------------------------------------------------------------------------------------------
304 // INGAME SHIP SELECT SCREEN
305 //
306 static char *Multi_ingame_join_bitmap_fname[GR_NUM_RESOLUTIONS] = {
307  "MultiIngame", // GR_640
308  "2_MultiIngame" // GR_1024
309 };
310 
311 static char *Multi_ingame_join_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
312  "MultiIngame-M", // GR_640
313  "2_MultiIngame-M" // GR_1024
314 };
315 
316 
317 // button defs
318 #define MULTI_INGAME_JOIN_NUM_BUTTONS 2
319 #define MIJ_CANCEL 0
320 #define MIJ_JOIN 1
321 
323  { // GR_640
324  ui_button_info( "MIB_00", 532, 434, 510, 413, 0 ), // cancel
325  ui_button_info( "MIB_01", 572, 428, 585, 413, 1 ), // join
326  },
327  { // GR_1024
328  ui_button_info( "2_MIB_00", 851, 695, 916, 685, 0 ), // cancel
329  ui_button_info( "2_MIB_01", 916, 685, 950, 665, 1 ), // join
330  }
331 };
332 
333 #define MULTI_INGAME_JOIN_NUM_TEXT 8
334 
336  { // GR_640
337  {"Cancel", 387, 510, 413, UI_XSTR_COLOR_PINK, -1, &Multi_ingame_join_buttons[GR_640][MIJ_CANCEL].button},
338  {"Join", 1303, 585, 413, UI_XSTR_COLOR_PINK, -1, &Multi_ingame_join_buttons[GR_640][MIJ_JOIN].button},
339  {"Select Ship", 317, 39, 6, UI_XSTR_COLOR_PINK, -1, NULL},
340  {"name", 1423, 39, 28, UI_XSTR_COLOR_GREEN, -1, NULL},
341  {"class", 1424, 145, 28, UI_XSTR_COLOR_GREEN, -1, NULL},
342  {"status", 1425, 214, 28, UI_XSTR_COLOR_GREEN, -1, NULL},
343  {"primary", 1426, 295, 28, UI_XSTR_COLOR_GREEN, -1, NULL},
344  {"secondary", 1427, 440, 28, UI_XSTR_COLOR_GREEN, -1, NULL}
345  },
346  { // GR_1024
347  {"Cancel", 387, 843, 665, UI_XSTR_COLOR_PINK, -1, &Multi_ingame_join_buttons[GR_1024][MIJ_CANCEL].button},
348  {"Join", 1303, 950, 665, UI_XSTR_COLOR_PINK, -1, &Multi_ingame_join_buttons[GR_1024][MIJ_JOIN].button},
349  {"Select Ship", 317, 63, 14, UI_XSTR_COLOR_PINK, -1, NULL},
350  {"name", 1423, 63, 45, UI_XSTR_COLOR_GREEN, -1, NULL},
351  {"class", 1424, 233, 45, UI_XSTR_COLOR_GREEN, -1, NULL},
352  {"status", 1425, 343, 45, UI_XSTR_COLOR_GREEN, -1, NULL},
353  {"primary", 1426, 473, 45, UI_XSTR_COLOR_GREEN, -1, NULL},
354  {"secondary", 1427, 704, 45, UI_XSTR_COLOR_GREEN, -1, NULL}
355  }
356 };
357 
358 #define MI_FIELD_X 0
359 #define MI_FIELD_Y 1
360 #define MI_FIELD_W 2
361 #define MI_FIELD_H 3
362 
363 static int Mi_width[GR_NUM_RESOLUTIONS] = {
364  569, // GR_640
365  910 // GR_1024
366 };
367 
368 static int Mi_height[GR_NUM_RESOLUTIONS] = {
369  339, // GR_640
370  542 // GR_1024
371 };
372 
373 static int Mi_spacing[GR_NUM_RESOLUTIONS] = {
374  30,
375  48
376 };
377 
378 static int Mi_name_field[GR_NUM_RESOLUTIONS][4] = {
379  // GR_640
380  {
381  33, // x
382  49, // y
383  100, // width
384  339 // height
385  },
386  // GR_1024
387  {
388  53, // x
389  78, // y
390  160, // width
391  542 // height
392  }
393 };
394 
395 static int Mi_class_field[GR_NUM_RESOLUTIONS][4] = {
396  // GR_640
397  {
398  140, // x
399  49, // y
400  59, // width
401  339 // height
402  },
403  // GR_1024
404  {
405  224, // x
406  78, // y
407  94, // width
408  542 // height
409  }
410 };
411 
412 static int Mi_status_field[GR_NUM_RESOLUTIONS][4] = {
413  // GR_640
414  {
415  209, // x
416  49, // y
417  69, // width
418  339 // height
419  },
420  // GR_1024
421  {
422  334, // x
423  78, // y
424  110, // width
425  542 // height
426  }
427 };
428 
429 static int Mi_primary_field[GR_NUM_RESOLUTIONS][4] = {
430  // GR_640
431  {
432  287, // x
433  49, // y
434  145, // width
435  339 // height
436  },
437  // GR_1024
438  {
439  459, // x
440  78, // y
441  232, // width
442  542 // height
443  }
444 };
445 
446 static int Mi_secondary_field[GR_NUM_RESOLUTIONS][4] = {
447  // GR_640
448  {
449  441, // x
450  49, // y
451  145, // width
452  339 // height
453  },
454  // GR_1024
455  {
456  706, // x
457  78, // y
458  232, // width
459  542 // height
460  }
461 };
462 
463 // for timing a player out
464 static int Multi_ingame_timer_coords[GR_NUM_RESOLUTIONS][2] = {
465  {
466  // GR_640
467  26,
468  411
469  },
470  {
471  // GR_1024
472  42,
473  658
474  }
475 };
476 
477 //#define MULTI_INGAME_TIME_LEFT_X 26
478 //#define MULTI_INGAME_TIME_LEFT_Y 411
479 
480 #define MULTI_INGAME_TIME_SECONDS (1000 * 15)
482 
483 // uses MULTI_JOIN_REFRESH_TIME as its timestamp
484 UI_WINDOW Multi_ingame_window; // the window object for the join screen
485 UI_BUTTON Multi_ingame_select_button; // for selecting list items
486 int Multi_ingame_bitmap; // the background bitmap
487 
488 // ship class icons
489 #define MULTI_INGAME_MAX_SHIP_ICONS 40
490 typedef struct is_icon {
493 } is_icon;
496 
497 // # of available ships (also == the # currently being displayed)
499 
500 // signatures for each of the available ships
502 
503 // net signature of the ship we've requested to grab as an ingame joiner (waiting for server response if >= 0)
505 
506 // the index into the list of the ship currently selected
508 
509 // temporary stuff - used only until we come up with a more permanent interface for this screen
510 #define MAX_INGAME_SHIPS 50
511 #define INGAME_FINAL_TIMEOUT 4000
512 
514 //LOCAL int Ingame_final_timeout;
515 
516 //XSTR:ON
517 
518 // local variables to hold ship/obj/ai information for the joiner. We need to
519 // create a bogus ship so that packets that the joiner receives during his join
520 // have valid Player_ship, Player_obj, and Player_ai to work with
522 
523 // display the available ships (OF_COULD_BE_PLAYER flagged)
525 
526 // try and scroll the selected ship up
528 
529 // try and scroll the selected ship down
531 
532 // handle all timeout details
534 
536 {
537  int idx;
538 
539  // lookup through all available ship icons
540  for(idx=0;idx<Multi_ingame_num_ship_icons;idx++){
541  if(Multi_ingame_ship_icon[idx].ship_class == ship_class){
542  return idx;
543  }
544  }
545 
546  // couldn't find it
547  return -1;
548 }
549 
551 {
552  int first_frame, num_frames, idx, s_idx;
553 
554  // zero out the icon handles
555  for(idx=0;idx<MULTI_INGAME_MAX_SHIP_ICONS;idx++){
556  Multi_ingame_ship_icon[idx].ship_class = -1;
557  for(s_idx=0;s_idx<NUM_ICON_FRAMES;s_idx++){
558  Multi_ingame_ship_icon[idx].bmaps[s_idx] = -1;
559  }
560  }
562 
563  // traverse through all ship types
564  for(auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it) {
565  // if there is a valid icon for this ship
566  if((it->icon_filename[0] != '\0') && (Multi_ingame_num_ship_icons < MULTI_INGAME_MAX_SHIP_ICONS)) {
567  // set the ship class
568  Multi_ingame_ship_icon[Multi_ingame_num_ship_icons].ship_class = std::distance(Ship_info.cbegin(), it);
569 
570  // load in the animation frames for the icon
571  first_frame = bm_load_animation(it->icon_filename, &num_frames);
572  if ( first_frame == -1 ) {
573  Int3(); // Could not load in icon frames.. get Dave
574  }
575  for ( s_idx = 0; s_idx < num_frames; s_idx++ ) {
576  Multi_ingame_ship_icon[Multi_ingame_num_ship_icons].bmaps[s_idx] = first_frame+s_idx;
577  }
578 
580  }
581  }
582 }
583 
585 {
586  int idx,s_idx;
587 
588  // unload all the bitmaps
589  for(idx=0;idx<Multi_ingame_num_ship_icons;idx++){
590  for(s_idx=0;s_idx<NUM_ICON_FRAMES;s_idx++){
591  if(Multi_ingame_ship_icon[idx].bmaps[s_idx] != -1){
592  bm_release(Multi_ingame_ship_icon[idx].bmaps[s_idx]);
593  Multi_ingame_ship_icon[idx].bmaps[s_idx] = -1;
594  }
595  }
596  }
597 }
598 
599 // ingame join ship selection screen init
601 {
603  // ushort net_signature;
604  int idx;
605 
607  Net_player->m_player->objnum = -1;
608 
609  // create a ship, then find a ship to copy crucial information from. Save and restore the wing
610  // number to be safe.
611  /*
612  wingnum_save = Player_start_pobject->wingnum;
613  net_signature = Player_start_pobject->net_signature;
614  goals_save = Player_start_pobject->ai_goals;
615  Player_start_pobject->wingnum = -1;
616  Player_start_pobject->net_signature = 0;
617  Player_start_pobject->ai_goals = -1;
618  objnum = parse_create_object( Player_start_pobject );
619  Player_start_pobject->wingnum = wingnum_save;
620  Player_start_pobject->net_signature = net_signature;
621  Player_start_pobject->ai_goals = goals_save;
622 
623  if ( objnum == -1 ) {
624  nprintf(("Network", "Bailing ingame join because unable to create parse object player ship\n"));
625  multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_INGAME_SHIP);
626  return;
627  }
628 
629  // make it invalid
630  Player_obj = &Objects[objnum];
631  Player_obj->net_signature = 0;
632  Player_ship = &Ships[Player_obj->instance];
633  strcpy_s(Player_ship->ship_name, NOX("JIP Ship"));
634  Player_ai = &Ai_info[Player_ship->ai_index];
635  */
636 
637  // load the temp ship icons
639 
640  // blast all the ingame ship signatures
641  memset(Multi_ingame_ship_sigs,0,sizeof(ushort) * MAX_PLAYERS);
642 
643  // the index into the list of the ship currently selected
645 
646  // initialize the time he has left to select a ship
648 
649  // initialize GUI data
650 
651  // create the interface window
652  Multi_ingame_window.create(0,0,gr_screen.max_w_unscaled,gr_screen.max_h_unscaled,0);
653  Multi_ingame_window.set_mask_bmap(Multi_ingame_join_bitmap_mask_fname[gr_screen.res]);
654 
655  // load the background bitmap
656  Multi_ingame_bitmap = bm_load(Multi_ingame_join_bitmap_fname[gr_screen.res]);
657  if(Multi_ingame_bitmap < 0)
658  Error(LOCATION, "Couldn't load background bitmap for ingame join");
659 
660  // create the interface buttons
661  for(idx=0; idx<MULTI_INGAME_JOIN_NUM_BUTTONS; idx++) {
662  // create the object
663  Multi_ingame_join_buttons[gr_screen.res][idx].button.create(&Multi_ingame_window, "", Multi_ingame_join_buttons[gr_screen.res][idx].x, Multi_ingame_join_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
664 
665  // set the sound to play when highlighted
667 
668  // set the ani for the button
669  Multi_ingame_join_buttons[gr_screen.res][idx].button.set_bmaps(Multi_ingame_join_buttons[gr_screen.res][idx].filename);
670 
671  // set the hotspot
672  Multi_ingame_join_buttons[gr_screen.res][idx].button.link_hotspot(Multi_ingame_join_buttons[gr_screen.res][idx].hotspot);
673  }
674 
675  // create all xstrs
676  for(idx=0; idx<MULTI_INGAME_JOIN_NUM_TEXT; idx++) {
677  Multi_ingame_window.add_XSTR(&Multi_ingame_join_text[gr_screen.res][idx]);
678  }
679 
680  // create the list item select button
681  Multi_ingame_select_button.create(&Multi_ingame_window, "", Mi_name_field[gr_screen.res][MI_FIELD_X], Mi_name_field[gr_screen.res][MI_FIELD_Y], Mi_width[gr_screen.res], Mi_height[gr_screen.res], 0, 1);
682  Multi_ingame_select_button.hide();
683 
684  // load freespace stuff
685  // JAS: Code to do paging used to be here.
686 }
687 
688 // process all ship list related details
690 {
691  int select_index,y;
692 
693  // if we currently don't have any ships selected, but we've got items on the list, select the first one
697  }
698 
699  // if we currently have a ship selected, but it disappears, select the next ship (is possible0
703  }
704 
705  // if the player clicked on the select button, see if the selection has changed
706  if(Multi_ingame_select_button.pressed()){
707  Multi_ingame_select_button.get_mouse_pos(NULL,&y);
708  select_index = y / Mi_spacing[gr_screen.res];
709 
710  // if we've selected a valid item
711  if((select_index >= 0) && (select_index < Multi_ingame_num_avail)){
712  // if we're not selected the same item, play a sound
713  if(Multi_ingame_ship_selected != select_index){
715  }
716 
717  // select the item
718  Multi_ingame_ship_selected = select_index;
719  }
720  }
721 }
722 
723 
724 // determines if a button was pressed, and acts accordingly
726 {
727  int idx;
728  for(idx=0; idx<MULTI_INGAME_JOIN_NUM_BUTTONS; idx++) {
729  // we only really need to check for one button pressed at a time,
730  // so we can break after finding one.
731  if(Multi_ingame_join_buttons[gr_screen.res][idx].button.pressed()) {
733  break;
734  }
735  }
736 }
737 
738 // a button was pressed, so make it do its thing
739 // this is the "acting accordingly" part
741 {
742  switch(n) {
743  case MIJ_CANCEL:
745  break;
746  case MIJ_JOIN:
747  // don't do further processing if the game is paused
749  return;
750 
751  if(Multi_ingame_join_sig == 0) {
752  // if he has a valid ship selected
753  if(Multi_ingame_ship_selected >= 0) {
755 
756  // select the sig of this ship and send a request for it
758 
759  // send a request to the
761  } else {
763  }
764  } else {
766  }
767 
768  break;
769  default:
770  // how did this happen?
771  Int3();
772  }
773 }
774 
775 
776 // ingame join ship selection screen do
778 {
779 
780 
781  int k = Multi_ingame_window.process();
782 
783  // process any keypresses
784  switch(k){
785  case KEY_ESC :
787  break;
788 
789  case KEY_UP:
791  break;
792 
793  case KEY_DOWN:
795  break;
796  }
797 
798  // process button presses
799  // multi_ingame_process_buttons();
801 
802  // process any ship list related events
804 
805  // draw the background, etc
806  gr_reset_clip();
808  if(Multi_ingame_bitmap != -1){
811  }
812  Multi_ingame_window.draw();
813 
814  // handle all timeout details. blitting, etc
816 
817  // display the available ships
819 
820  // flip the buffer
821  gr_flip();
822 }
823 
824 // ingame join ship select close
826 {
827  // unload any bitmaps
829  nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_ingame_join_bitmap_fname[gr_screen.res]));
830  }
831 
832  // unload all the ship class icons
834 
835  // destroy the UI_WINDOW
836  Multi_ingame_window.destroy();
837 
838  // stop main hall music
839  main_hall_stop_music(true);
840 }
841 
842 // display an individual ships information, starting at the indicated y pixel value
843 void multi_ingame_join_display_ship(object *objp,int y_start)
844 {
845  int icon_num,idx;
846  int y_spacing;
847  ship_weapon *wp;
848 
849  int line_height = gr_get_font_height() + 1;
850 
851  // blit the ship name itself
853  gr_string(Mi_name_field[gr_screen.res][MI_FIELD_X],y_start+10, Ships[objp->instance].ship_name, GR_RESIZE_MENU);
854 
855  // blit the ship class icon
857  if(icon_num != -1){
858  gr_set_bitmap(Multi_ingame_ship_icon[icon_num].bmaps[0]);
859  gr_bitmap(Mi_class_field[gr_screen.res][MI_FIELD_X] + 15, y_start, GR_RESIZE_MENU);
860  }
861 
863  wp = &Ships[objp->instance].weapons;
864 
865  // blit the ship's primary weapons
866  y_spacing = (Mi_spacing[gr_screen.res] - (wp->num_primary_banks * line_height)) / 2;
867  for(idx=0;idx<wp->num_primary_banks;idx++){
868  gr_string(Mi_primary_field[gr_screen.res][MI_FIELD_X], y_start + y_spacing + (idx * line_height), Weapon_info[wp->primary_bank_weapons[idx]].name, GR_RESIZE_MENU);
869  }
870 
871  // blit the ship's secondary weapons
872  y_spacing = (Mi_spacing[gr_screen.res] - (wp->num_secondary_banks * line_height)) / 2;
873  for(idx=0;idx<wp->num_secondary_banks;idx++){
874  gr_string(Mi_secondary_field[gr_screen.res][MI_FIELD_X], y_start + y_spacing + (idx * line_height), Weapon_info[wp->secondary_bank_weapons[idx]].name, GR_RESIZE_MENU);
875  }
876 
877  // blit the shield/hull integrity
878  hud_shield_show_mini(objp, Mi_status_field[gr_screen.res][MI_FIELD_X] + 15, y_start + 3,5,7);
879 }
880 
881 // display the available ships (OF_COULD_BE_PLAYER flagged)
883 {
884  ship_obj *moveup;
885 
886  // recalculate this # every frame
888 
889  // display a background highlight rectangle for any selected lines
890  if(Multi_ingame_ship_selected != -1){
891  int y_start = (Mi_name_field[gr_screen.res][MI_FIELD_Y] + (Multi_ingame_ship_selected * Mi_spacing[gr_screen.res]));
892 
893  // draw the border
895  gr_line(Mi_name_field[gr_screen.res][MI_FIELD_X]-1,y_start-1, (Mi_name_field[gr_screen.res][MI_FIELD_X]-1) + (Mi_width[gr_screen.res]+2),y_start-1, GR_RESIZE_MENU);
896  gr_line(Mi_name_field[gr_screen.res][MI_FIELD_X]-1,y_start + Mi_spacing[gr_screen.res] - 2, (Mi_name_field[gr_screen.res][MI_FIELD_X]-1) + (Mi_width[gr_screen.res]+2),y_start + Mi_spacing[gr_screen.res] - 2, GR_RESIZE_MENU);
897  gr_line(Mi_name_field[gr_screen.res][MI_FIELD_X]-1,y_start, Mi_name_field[gr_screen.res][MI_FIELD_X]-1, y_start + Mi_spacing[gr_screen.res] - 2, GR_RESIZE_MENU);
898  gr_line((Mi_name_field[gr_screen.res][MI_FIELD_X]-1) + (Mi_width[gr_screen.res]+2), y_start,(Mi_name_field[gr_screen.res][MI_FIELD_X]-1) + (Mi_width[gr_screen.res]+2),y_start + Mi_spacing[gr_screen.res] - 2, GR_RESIZE_MENU);
899  }
900 
901  moveup = GET_FIRST(&Ship_obj_list);
902  while(moveup != END_OF_LIST(&Ship_obj_list)){
903  if( !(Ships[Objects[moveup->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) && (Objects[moveup->objnum].flags & OF_COULD_BE_PLAYER) ) {
904  // display the ship
906 
907  // set the ship signature
909 
910  // inc the # available
912  }
913  moveup = GET_NEXT(moveup);
914  }
915 }
916 
917 // try and scroll the selected ship up
919 {
923  } else {
925  }
926 }
927 
928 // try and scroll the selected ship down
930 {
934  } else {
936  }
937 }
938 
939 // handle all timeout details
941 {
942  /*
943  // uncomment this block to disable the timer
944  gr_set_color_fast(&Color_bright_red);
945  gr_string(Multi_ingame_timer_coords[gr_screen.res][0], Multi_ingame_timer_coords[gr_screen.res][1], "Timer disabled!!", GR_RESIZE_MENU);
946  return;
947  */
948 
949  // if we've timed out, leave the game
952  return;
953  }
954 
955  // otherwise, blit how much time we have left
956  int time_left = timestamp_until(Ingame_time_left) / 1000;
957  char tl_string[100];
959  memset(tl_string,0,100);
960  sprintf(tl_string,XSTR("Time remaining : %d s\n",682),time_left);
961  gr_string(Multi_ingame_timer_coords[gr_screen.res][0], Multi_ingame_timer_coords[gr_screen.res][1], tl_string, GR_RESIZE_MENU);
962 }
963 
964 
965 // --------------------------------------------------------------------------------------------------
966 // PACKET HANDLER functions
967 // these are also defined in multimsgs.h, but the implementations are in the module for the sake of convenience
968 //
969 
970 #define INGAME_PACKET_SLOP 75 // slop value used for packets to ingame joiner
971 
973 {
974  int offset, sflags, sflags2, oflags, team, j;
975  ubyte p_type;
976  ushort net_signature;
977  short wing_data;
978  int team_val, slot_index, idx;
979  char ship_name[255] = "";
980  object *objp;
981  int net_sig_modify;
982 
983  // go through the ship obj list and delete everything. YEAH
985 
986  // no player object
987  Player_obj = NULL;
988  Player_ship = NULL;
989  Player_ai = NULL;
990 
991  // delete all ships
992  for(idx=0; idx<MAX_SHIPS; idx++){
993  if((Ships[idx].objnum >= 0) && (Ships[idx].objnum < MAX_OBJECTS)){
994  obj_delete(Ships[idx].objnum);
995  }
996  }
997 
999  }
1000 
1001  offset = HEADER_LENGTH;
1002 
1003  // go
1004  GET_DATA( p_type );
1005  while ( p_type == INGAME_SHIP_NEXT ) {
1006  p_object *p_objp;
1007  int ship_num, objnum;
1008 
1009  GET_STRING( ship_name );
1010  GET_USHORT( net_signature );
1011  GET_INT( sflags );
1012  GET_INT( sflags2 );
1013  GET_INT( oflags );
1014  GET_INT( team );
1015  GET_SHORT( wing_data );
1016  net_sig_modify = 0;
1017  if(wing_data >= 0){
1018  GET_INT(Wings[wing_data].current_wave);
1019  net_sig_modify = Wings[wing_data].current_wave - 1;
1020  }
1021 
1022  // lookup ship in the original ships array
1023  p_objp = mission_parse_get_parse_object(net_signature);
1024  if(p_objp == NULL){
1025  // if this ship is part of wing not on its current wave, look for its "original" by subtracting out wave #
1026  p_objp = mission_parse_get_arrival_ship((ushort)(net_signature - (ushort)net_sig_modify));
1027  }
1028  if(p_objp == NULL){
1029  Int3();
1030  nprintf(("Network", "Couldn't find ship %s in either arrival list or in mission", ship_name));
1032  return;
1033  }
1034 
1035  // go ahead and create the parse object. Set the network signature of this guy before
1036  // creation
1037 
1038  // multi_set_network_signature uncommented by Kazan on 11-04-2004
1039  multi_set_network_signature( net_signature, MULTI_SIG_SHIP );
1040  objnum = parse_create_object( p_objp );
1041  ship_num = Objects[objnum].instance;
1042  Objects[objnum].flags = oflags;
1043  Objects[objnum].net_signature = net_signature;
1044 
1045  // assign any common data
1046  strcpy_s(Ships[ship_num].ship_name, ship_name);
1047  Ships[ship_num].flags = sflags;
1048  Ships[ship_num].flags2 = sflags2;
1049  Ships[ship_num].team = team;
1050  Ships[ship_num].wingnum = (int)wing_data;
1051 
1052  GET_DATA( p_type );
1053  }
1054 
1055  PACKET_SET_SIZE();
1056 
1057  // if we have reached the end of the list and change our network state
1058  if ( p_type == INGAME_SHIP_LIST_EOL ) {
1059  // merge all created list
1061 
1062  // fixup player ship stuff
1063  for(idx=0; idx<MAX_SHIPS; idx++){
1064  if(Ships[idx].objnum < 0){
1065  continue;
1066  }
1067 
1068  // get the team and slot. Team will be -1 when it isn't a part of player wing. So, if
1069  // not -1, then be sure we have a valid slot, then change the ship type, etc.
1070  objp = &Objects[Ships[idx].objnum];
1071  multi_ts_get_team_and_slot(Ships[idx].ship_name, &team_val, &slot_index);
1072  if ( team_val != -1 ) {
1073  Assert( slot_index != -1 );
1074 
1075  // change the ship type and the weapons
1076  change_ship_type(objp->instance, Wss_slots_teams[team_val][slot_index].ship_class);
1077  wl_bash_ship_weapons(&Ships[idx].weapons, &Wss_slots_teams[team_val][slot_index]);
1078 
1079  // Be sure to mark this ship as as a could_be_player
1080  obj_set_flags( objp, objp->flags | OF_COULD_BE_PLAYER );
1081  objp->flags &= ~OF_PLAYER_SHIP;
1082 
1083  // if this is a player ship, make sure we find out who's it is and set their objnum accordingly
1084  for( j = 0; j < MAX_PLAYERS; j++){
1085  if(MULTI_CONNECTED(Net_players[j]) && (Net_players[j].m_player->objnum == Objects[Ships[idx].objnum].net_signature)) {
1086  multi_assign_player_ship( j, objp, Ships[idx].ship_info_index );
1087  objp->flags |= OF_PLAYER_SHIP;
1088  objp->flags &= ~OF_COULD_BE_PLAYER;
1089  break;
1090  }
1091  }
1092  }
1093  }
1094 
1095  // notify the server that we're all good.
1098 
1099  // add some mission sync text
1100  multi_common_add_text(XSTR("Ships packet ack (ingame)\n",683));
1101  }
1102 }
1103 
1105 {
1107  ubyte p_type;
1108  ship_obj *so;
1109  int packet_size;
1110  short wing_data;
1111 
1113 
1114  // essentially, we are going to send a list of ship names to the joiner for ships that are not
1115  // in wings. The joiner will take the list, create any ships which should be created, and delete all
1116  // other ships after the list is sent.
1117  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
1118  ship *shipp;
1119 
1120  shipp = &Ships[Objects[so->objnum].instance];
1121 
1122  // skip all wings.
1123  // if ( shipp->wingnum != -1 ){
1124  // continue;
1125  // }
1126 
1127  if ( Objects[so->objnum].net_signature == STANDALONE_SHIP_SIG ){
1128  continue;
1129  }
1130 
1131  // add the ship name and other information such as net signature, ship and object(?) flags.
1132  p_type = INGAME_SHIP_NEXT;
1133  ADD_DATA( p_type );
1134  ADD_STRING( shipp->ship_name );
1135  ADD_USHORT( Objects[so->objnum].net_signature );
1136  ADD_INT( shipp->flags );
1137  ADD_INT( shipp->flags2 );
1138  ADD_INT( Objects[so->objnum].flags );
1139  ADD_INT( shipp->team );
1140  wing_data = (short)shipp->wingnum;
1141  ADD_SHORT(wing_data);
1142  if(wing_data >= 0){
1143  ADD_INT(Wings[wing_data].current_wave);
1144  }
1145 
1146  // don't send anymore data if we are getting close to the maximum size of this packet. Send it off and
1147  // keep going
1148  if ( packet_size > (MAX_PACKET_SIZE - INGAME_PACKET_SLOP) ) {
1149  p_type = INGAME_SHIP_LIST_EOP;
1150  ADD_DATA( p_type );
1151  multi_io_send_reliable(player, data, packet_size);
1153  }
1154  }
1155 
1156  // end of the ship list!!!
1157  p_type = INGAME_SHIP_LIST_EOL;
1158  ADD_DATA( p_type );
1159  multi_io_send_reliable(player, data, packet_size);
1160 }
1161 
1163 {
1164  Int3();
1165 }
1166 /*
1167 // code to process the wing data from a server.
1168 void process_ingame_wings_packet( ubyte *data, header *hinfo )
1169 {
1170  int offset, wingnum;
1171  ubyte p_type, what;
1172 
1173  offset = HEADER_LENGTH;
1174 
1175  GET_DATA( p_type );
1176 
1177  // p_type tells us whether to stop or not
1178  while ( p_type == INGAME_WING_NEXT ) {
1179  wing *wingp;
1180 
1181  // get the wingnum and a pointer to it. The game stores data for all wings always, so this
1182  // is perfectly valid
1183  GET_DATA( wingnum );
1184  wingp = &Wings[wingnum];
1185 
1186  GET_DATA( what );
1187  if ( what == INGAME_WING_NOT_ARRIVED ) {
1188  Assert( wingp->total_arrived_count == 0 ); // this had better be true!!!
1189  } else if ( what == INGAME_WING_DEPARTED ) {
1190  // mark the wing as gone. if it isn't, it soon will be. Maybe we should send more information
1191  // about these wings later (like total_arrived_count, etc), but we will see.
1192  wingp->flags |= WF_WING_GONE;
1193  } else {
1194  int total_arrived_count, current_count, current_wave, i, j;
1195  ushort signature;
1196  int shipnum;
1197 
1198  // the wing is present in the mission on the server. Get the crucial information about the
1199  // wing. Then get the ships for this wing in order on the client machine
1200  GET_DATA( total_arrived_count );
1201  GET_DATA( current_count );
1202  GET_DATA( current_wave );
1203 
1204  Assert( current_wave > 0 );
1205  Assert( total_arrived_count > 0 );
1206 
1207  // for this wing, strip it down to nothing. Let the parse object ocde recreate the
1208  // wing from the parse objects, then bash any weapons, etc for player wings. We need
1209  // to do this because we might actually wind up with > MAX_SHIPS_PER_WING if we
1210  // don't delete them all first, and have a > 0 threshold, and are on something other
1211  // than the first wave. Only do this for non-player wings.
1212 
1213  nprintf(("Network", "Clearing %s -- %d ships\n", wingp->name, wingp->current_count));
1214  for ( i = 0; i < wingp->current_count; i++ ) {
1215  int index, objnum;
1216 
1217  index = wingp->ship_index[i];
1218  Assert( index != -1 );
1219  objnum = Ships[index].objnum;
1220  Assert( objnum != -1 );
1221 
1222  // delete the object since we are filling the wing again anyway.
1223  obj_delete( objnum );
1224  Objects[objnum].net_signature = 0; // makes this object "invalid" until dead.
1225  if ( Objects[objnum].type == OBJ_GHOST ) {
1226  nprintf(("Network", "Marking ghost objnum %d as dead\n", objnum));
1227  Objects[objnum].flags |= OF_SHOULD_BE_DEAD;
1228  }
1229  Ingame_ships_to_delete[index] = 0; // be sure that this guy doesn't get deleted, since we already deleted it
1230  wingp->ship_index[i] = -1;
1231  }
1232  wingp->current_count = 0;
1233  wingp->total_arrived_count = 0;
1234 
1235  // now, recreate all the ships needed
1236  for (i = 0; i < current_count; i++ ) {
1237  int which_one, team, slot_index, specific_instance;
1238  ship *shipp;
1239  object *objp;
1240 
1241  GET_DATA( signature );
1242 
1243  // assign which_one to be the given signature - wing's base signature. This let's us
1244  // know which ship to create (i.e. the total_arrivel_count);
1245  which_one = signature - wingp->net_signature;
1246  Assert( (which_one >= 0) && (which_one < (wingp->net_signature + (wingp->wave_count*wingp->num_waves))) );
1247  wingp->total_arrived_count = (ushort)which_one;
1248 
1249  // determine which ship in the ahip arrival list this guy is. It is a 0 based index
1250  specific_instance = which_one % wingp->wave_count;
1251 
1252  // call parse_wing_create_ships making sure that we only ever create 1 ship at a time. We don't
1253  // want parse_wing_create_ships() to assign network signature either. We will directly
1254  // assign it here.
1255 
1256  wingp->current_wave = 0; // make it the first wave. Ensures that ships don't get removed off the list
1257  parse_wing_create_ships( wingp, 1, 1, specific_instance );
1258  shipnum = wingp->ship_index[wingp->current_count-1];
1259  Ingame_ships_to_delete[shipnum] = 0; // "unmark" this ship so it doesn't get deleted.
1260 
1261  // kind of stupid, but bash the name since it won't get recreated properly from
1262  // the parse_wing_create_ships call.
1263  shipp = &Ships[shipnum];
1264  wing_bash_ship_name(shipp->ship_name, wingp->name, which_one + 1);
1265  nprintf(("Network", "Created %s\n", shipp->ship_name));
1266 
1267  objp = &Objects[shipp->objnum];
1268  objp->net_signature = (ushort)(wingp->net_signature + which_one);
1269 
1270  // get the team and slot. Team will be -1 when it isn't a part of player wing. So, if
1271  // not -1, then be sure we have a valid slot, then change the ship type, etc.
1272  multi_ts_get_team_and_slot(shipp->ship_name, &team, &slot_index);
1273  if ( team != -1 ) {
1274  Assert( slot_index != -1 );
1275 
1276  // change the ship type and the weapons
1277  change_ship_type(objp->instance, Wss_slots_teams[team][slot_index].ship_class);
1278  wl_bash_ship_weapons(&shipp->weapons,&Wss_slots_teams[team][slot_index]);
1279 
1280  // Be sure to mark this ship as as a could_be_player
1281  obj_set_flags( objp, objp->flags | OF_COULD_BE_PLAYER );
1282  objp->flags &= ~OF_PLAYER_SHIP;
1283  }
1284 
1285  // if this is a player ship, make sure we find out who's it is and set their objnum accordingly
1286  for( j = 0; j < MAX_PLAYERS; j++){
1287  if(MULTI_CONNECTED(Net_players[j]) && (Net_players[j].player->objnum == signature)) {
1288  Assert( team != -1 ); // to help trap errors!!!
1289  nprintf(("Network", "Making %s ship for %s\n", Ships[shipnum].ship_name, Net_players[j].player->callsign));
1290  multi_assign_player_ship( j, objp, Ships[shipnum].ship_info_index );
1291  objp->flags |= OF_PLAYER_SHIP;
1292  objp->flags &= ~OF_COULD_BE_PLAYER;
1293  break;
1294  }
1295  }
1296  }
1297 
1298 
1299  // we will have no ships in any wings at this point (we didn't create any when we loaded the
1300  // mission). Set the current wave of this wing to be 1 less than was passed in since this value
1301  // will get incremented in parse_wing_create_ships;
1302  wingp->current_wave = current_wave;
1303  wingp->total_arrived_count = total_arrived_count;
1304  }
1305 
1306  GET_DATA( p_type );
1307  }
1308 
1309  PACKET_SET_SIZE();
1310 
1311  // if we have reached the end of the list change our network state
1312  if ( p_type == INGAME_WING_LIST_EOL ) {
1313  Net_player->state = NETPLAYER_STATE_INGAME_WINGS;
1314  send_netplayer_update_packet();
1315 
1316  // add some mission sync text
1317  multi_common_add_text(XSTR("Wings packet (ingame)\n",684));
1318  }
1319 
1320 }
1321 
1322 // function to send information about wings. We need to send enough information to let the client
1323 // construct or reconstruct any wings in the mission. We will rely on the fact that the host wing array
1324 // will exactly match the client wing array (in terms of number, and wing names)
1325 void send_ingame_wings_packet( net_player *player )
1326 {
1327  ubyte data[MAX_PACKET_SIZE];
1328  ubyte p_type;
1329  int packet_size, i;
1330  ubyte what;
1331 
1332  BUILD_HEADER( WINGS_INGAME_PACKET );
1333 
1334  // iterate through the wings list
1335  for ( i = 0; i < Num_wings; i++ ) {
1336  wing *wingp;
1337 
1338  wingp = &Wings[i];
1339 
1340  p_type = INGAME_WING_NEXT;
1341  ADD_DATA( p_type );
1342 
1343  ADD_DATA( i );
1344 
1345  // add wing data that the client needs. There are several conditions to send to clients:
1346  //
1347  // 1. wing hasn't arrived -- total_arrived_count will be 0
1348  // 2. wing is done (or currently departing)
1349  // 3. wing is present (any wave, any number of ships).
1350  //
1351  // 1 and 2 are easy to handle. (3) is the hardest.
1352  if ( wingp->total_arrived_count == 0 ) {
1353  what = INGAME_WING_NOT_ARRIVED;
1354  ADD_DATA( what );
1355  } else if ( wingp->flags & (WF_WING_GONE | WF_WING_DEPARTING) ) {
1356  what = INGAME_WING_DEPARTED;
1357  ADD_DATA( what );
1358  } else {
1359  int j;
1360 
1361  // include to code to possibly send more wing data here in this part of the if/else
1362  // chain. We can do this because MAX_WINGS * 8 (8 being the number of byte for a minimum
1363  // description of a wing) is always less than MAX_PACKET_SIZE. Checking here ensures that
1364  // we have enough space for *this* wing in the packet, and not the largest wing. The
1365  // formula below looks at number of ships in the wing, the name length, length of the signature,
1366  // and the size of the bytes added before the ship names. 32 accounts for a little slop
1367  if ( packet_size > (MAX_PACKET_SIZE - (wingp->current_count * (NAME_LENGTH+2) + 32)) ) {
1368  p_type = INGAME_WING_LIST_EOP;
1369  ADD_DATA( p_type );
1370  multi_io_send_reliable(player, data, packet_size);
1371  BUILD_HEADER( WINGS_INGAME_PACKET );
1372  }
1373  what = INGAME_WING_PRESENT;
1374  ADD_DATA( what );
1375  ADD_DATA( wingp->total_arrived_count );
1376  ADD_DATA( wingp->current_count );
1377  ADD_DATA( wingp->current_wave );
1378 
1379  // add the ship name and net signature of all ships currently in the wing.
1380  for ( j = 0; j < wingp->current_count; j++ ) {
1381  ship *shipp;
1382 
1383  shipp = &Ships[wingp->ship_index[j]];
1384  //ADD_STRING( shipp->ship_name );
1385  ADD_DATA( Objects[shipp->objnum].net_signature );
1386  }
1387  }
1388 
1389  }
1390 
1391  p_type = INGAME_WING_LIST_EOL;
1392  ADD_DATA( p_type );
1393 
1394  multi_io_send_reliable(player, data, packet_size);
1395 }
1396 */
1397 
1398 // send a request or a reply regarding ingame join ship choice
1400 {
1402  ship *shipp;
1403  ship_info *sip;
1404  int i, packet_size = 0;
1405  ushort signature;
1406  p_object *pobj;
1407 
1408  // add the data
1410 
1411  // add the code
1412  ADD_INT(code);
1413 
1414  // add any code specific data
1415  switch(code){
1416  case INGAME_SR_REQUEST:
1417  // add the net signature of the ship we're requesting
1418  signature = (ushort)rdata;
1419  ADD_USHORT( signature );
1420  break;
1421  case INGAME_SR_CONFIRM:
1422  // get a pointer to the ship
1423  shipp = &Ships[Objects[rdata].instance];
1424  sip = &Ship_info[shipp->ship_info_index];
1425 
1426  // add the most recent position and orientation for the requested ship
1427  ADD_VECTOR(Objects[rdata].pos);
1428  ADD_ORIENT(Objects[rdata].orient);
1429  ADD_INT( Missiontime ); // NOTE: this is a long so careful with swapping in 64-bit platforms - taylor
1430 
1431  // add the # of respawns this ship has left
1432  pobj = mission_parse_get_arrival_ship( Objects[rdata].net_signature );
1433  Assert(pobj != NULL);
1434  ADD_DATA(pobj->respawn_count);
1435 
1436  // add the ships ets settings
1437  val = (ubyte)shipp->weapon_recharge_index;
1438  ADD_DATA(val);
1439  val = (ubyte)shipp->shield_recharge_index;
1440  ADD_DATA(val);
1441  val = (ubyte)shipp->engine_recharge_index;
1442  ADD_DATA(val);
1443 
1444  // add the ballistic primary flag - Goober5000
1445  val = 0;
1446  if(sip->flags & SIF_BALLISTIC_PRIMARIES){
1447  val |= (1<<0);
1448  }
1449  ADD_DATA(val);
1450 
1451  // add current primary and secondary banks, and add link status
1452  val = (ubyte)shipp->weapons.current_primary_bank;
1453  ADD_DATA(val);
1454  val = (ubyte)shipp->weapons.current_secondary_bank;
1455  ADD_DATA(val);
1456 
1457  // add the current ammo count for secondary banks;
1458  val = (ubyte)shipp->weapons.num_secondary_banks; // for sanity checking
1459  ADD_DATA(val);
1460  for ( i = 0; i < shipp->weapons.num_secondary_banks; i++ ) {
1461  Assert( shipp->weapons.secondary_bank_ammo[i] < UCHAR_MAX );
1462  val = (ubyte)shipp->weapons.secondary_bank_ammo[i];
1463  ADD_DATA(val);
1464  }
1465 
1466  // add the current ammo count for primary banks - copied from above - Goober5000
1467  val = (ubyte)shipp->weapons.num_primary_banks; // for sanity checking
1468  ADD_DATA(val);
1469  for ( i = 0; i < shipp->weapons.num_primary_banks; i++ )
1470  {
1471  Assert( shipp->weapons.primary_bank_ammo[i] < UCHAR_MAX );
1472  val = (ubyte)shipp->weapons.primary_bank_ammo[i];
1473  ADD_DATA(val);
1474  }
1475 
1476  // add the link status of weapons
1477  // primary link status
1478  val = 0;
1479  if(shipp->flags & SF_PRIMARY_LINKED){
1480  val |= (1<<0);
1481  }
1482  if(shipp->flags & SF_SECONDARY_DUAL_FIRE){
1483  val |= (1<<1);
1484  }
1485  ADD_DATA(val);
1486  break;
1487  }
1488 
1489  // send the packet
1491  Assert(pl != NULL);
1492  multi_io_send_reliable(pl, data, packet_size);
1493  } else {
1494  multi_io_send_reliable(Net_player, data, packet_size);
1495  }
1496 
1497  // if this is a confirm to a player -- send data to the other players in the game telling them
1498  if ( (code == INGAME_SR_CONFIRM) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) ) {
1499  int player_num;
1500 
1501  player_num = NET_PLAYER_NUM(pl);
1502  code = INGAME_PLAYER_CHOICE;
1504  ADD_INT(code);
1505  ADD_INT(player_num);
1506  ADD_USHORT(Objects[rdata].net_signature);
1507  for (i = 0; i < MAX_PLAYERS; i++ ) {
1508  if(MULTI_CONNECTED(Net_players[i]) && (&Net_players[i] != Net_player) && (i != player_num) ) {
1509  multi_io_send_reliable(&Net_players[i], data, packet_size);
1510  }
1511  }
1512  }
1513 }
1514 
1515 // function to validate all players in the game according to their team select index. If discrepancies
1516 // are found, this function should be able to fix them up.
1518 {
1519  int i;
1520 
1521  for ( i = 0; i < MAX_PLAYERS; i++ ) {
1523  char ship_name[NAME_LENGTH];
1524  int shipnum, objnum, player_objnum;
1525 
1526  player_objnum = Net_players[i].m_player->objnum;
1527  if ( (Objects[player_objnum].type != OBJ_SHIP) && (Objects[player_objnum].type != OBJ_GHOST) ) {
1528  Int3();
1529  }
1530 
1531  multi_ts_get_shipname( ship_name, Net_players[i].p_info.team, Net_players[i].p_info.ship_index );
1532  Assert( ship_name != NULL );
1533  shipnum = ship_name_lookup( ship_name );
1534  if ( shipnum == -1 ) {
1535  // ship could be respawning
1536  continue;
1537  }
1538  objnum = Ships[shipnum].objnum;
1539  Assert( objnum != -1 );
1540 
1541  // if this guy's objnum isn't a ship, then it should proably be a ghost!!
1542  if ( Objects[objnum].type == OBJ_SHIP ) {
1543  if ( objnum != Net_players[i].m_player->objnum ) {
1544  Int3();
1545  Net_players[i].m_player->objnum = objnum;
1546  }
1547  } else {
1548  Assert( Objects[objnum].type == OBJ_GHOST );
1549  }
1550  }
1551  }
1552 }
1553 
1554 // process an ingame ship request packet
1556 {
1557  int code;
1558  object *objp;
1559  int offset = HEADER_LENGTH;
1560  int team, slot_index, i;
1561  uint respawn_count;
1562  ubyte val, num_secondary_banks, num_primary_banks;
1563  p_object *pobj;
1564  int player_num;
1565 
1566  // get the code
1567  GET_INT(code);
1568 
1569  switch(code){
1570  // a request for a ship from an ingame joiner
1571  case INGAME_SR_REQUEST:
1572  ushort sig_request;
1573 
1574  // lookup the player and make sure he doesn't already have an objnum (along with possible error conditions)
1575  GET_USHORT(sig_request);
1576  PACKET_SET_SIZE();
1577 
1578  player_num = find_player_id(hinfo->id);
1579  if(player_num == -1){
1580  nprintf(("Network","Received ingame ship request packet from unknown player!!\n"));
1581  break;
1582  }
1583 
1584  // make sure this player doesn't already have an object
1585  Assert(MULTI_CONNECTED(Net_players[player_num]));
1586  if(Net_players[player_num].m_player->objnum != -1){
1588  break;
1589  }
1590 
1591  // try and find the object
1592  objp = NULL;
1593  objp = multi_get_network_object(sig_request);
1594  if(objp == NULL || !(objp->flags & OF_COULD_BE_PLAYER)){
1596  break;
1597  }
1598 
1599  // Assign the player this objnum and ack him
1600  Net_players[player_num].m_player->objnum = OBJ_INDEX(objp);
1601  Net_players[player_num].state = NETPLAYER_STATE_IN_MISSION; // since he'll do this anyway...
1602  Net_players[player_num].flags &= ~(NETINFO_FLAG_INGAME_JOIN);
1603  multi_assign_player_ship( player_num, objp, Ships[objp->instance].ship_info_index );
1604 
1605  // update his ets and link status stuff
1607 
1608  objp->flags &= ~(OF_COULD_BE_PLAYER);
1609  objp->flags |= OF_PLAYER_SHIP;
1610 
1611  // send a player settings packet to update all other players of this guy's final choices
1613 
1614  // initialize datarate limiting for this guy
1615  multi_oo_rate_init(&Net_players[player_num]);
1616 
1617  // ack him
1619 
1620  // clear my ingame join flag so that others may join
1622 
1623  // clear his net stats
1624  scoring_level_init( &(Net_players[player_num].m_player->stats) );
1625  break;
1626 
1627  // a denial for the ship we requested from the server
1628  case INGAME_SR_DENY :
1629  PACKET_SET_SIZE();
1630 
1631  // set this to -1 so we can pick again
1633 
1634  // display a popup
1635  popup(PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been denied the requested ship",686));
1636  break;
1637 
1638  // a confirmation that we can use the selected ship
1639  case INGAME_SR_CONFIRM:
1640  // object *temp_objp;
1641 
1642  // delete the ship this ingame joiner was using. Unassign Player_obj so that this object
1643  // doesn't become a ghost.
1644  // temp_objp = Player_obj;
1645  // Player_obj = NULL;
1646  // obj_delete( OBJ_INDEX(temp_objp) );
1647 
1648  // get the object itself
1650  Assert(objp != NULL);
1651 
1652  // get its most recent position and orientation
1653  GET_VECTOR(objp->pos);
1654  GET_ORIENT(objp->orient);
1655  GET_INT( Missiontime ); // NOTE: this is a long so careful with swapping in 64-bit platforms - taylor
1656  GET_UINT( respawn_count );
1657 
1658  // tell the server I'm in the mission
1661 
1662  // setup our object
1663  Net_player->m_player->objnum = OBJ_INDEX(objp);
1664  Player_obj = objp;
1668 
1669  // must change the ship type and weapons. An ingame joiner know about the default class
1670  // and weapons for a ship, but these could have changed.
1671  multi_ts_get_team_and_slot(Player_ship->ship_name, &team, &slot_index);
1672  Assert( team != -1 );
1673  Assert( slot_index != -1 );
1674  change_ship_type(objp->instance, Wss_slots_teams[team][slot_index].ship_class);
1676 
1677  // get the parse object for it and assign the respawn count
1679  Assert(pobj != NULL);
1680  pobj->respawn_count = respawn_count;
1681 
1682  // get the ships ets settings
1683  GET_DATA(val);
1685  GET_DATA(val);
1687  GET_DATA(val);
1689 
1690  // handle the ballistic primary flag - Goober5000
1691  GET_DATA(val);
1692  if(val & (1<<0)){
1694  }
1695 
1696  // get current primary and secondary banks, and add link status
1697  GET_DATA(val);
1699  GET_DATA(val);
1701 
1702  // secondary bank ammo data
1703  GET_DATA( num_secondary_banks );
1704  Assert( num_secondary_banks == Player_ship->weapons.num_secondary_banks );
1705  for ( i = 0; i < Player_ship->weapons.num_secondary_banks; i++ ) {
1706  GET_DATA(val);
1708  }
1709 
1710  // primary bank ammo data - copied from above - Goober5000
1711  GET_DATA( num_primary_banks );
1712  Assert( num_primary_banks == Player_ship->weapons.num_primary_banks );
1713  for ( i = 0; i < Player_ship->weapons.num_primary_banks; i++ )
1714  {
1715  GET_DATA(val);
1717  }
1718 
1719  // get the link status of weapons
1720  GET_DATA(val);
1721  if(val & (1<<0)){
1723  }
1724  if(val & (1<<1)){
1726  }
1727  PACKET_SET_SIZE();
1728 
1729  // be sure that this ships current primary/secondary weapons are valid. Easiest is to just
1730  // bash the values to 0!
1731  /*
1732  if ( Player_ship->weapons.current_primary_bank == -1 )
1733  Player_ship->weapons.current_primary_bank = 0;
1734  if ( Player_ship->weapons.current_secondary_bank == -1 )
1735  Player_ship->weapons.current_secondary_bank = 0;
1736  */
1737 
1739 
1740  // clear all object collision pairs, then add myself to the list
1741  extern void obj_reset_all_collisions();
1743  // obj_reset_pairs();
1744  // obj_add_pairs( OBJ_INDEX(Player_obj) );
1745 
1747 
1748  //multi_ingame_validate_players();
1749 
1750  // jump into the mission
1751  // NOTE : we check this flag because its possible that the player could have received an endgame packet in the same
1752  // frame as getting this confirmation. In that case, he should be quitting to the main menu. We must not make
1753  // him continue on into the mission
1754  if(!multi_endgame_ending()){
1756  }
1757  break;
1758 
1759  case INGAME_PLAYER_CHOICE: {
1760  ushort net_signature;
1761 
1762  // get the player number of this guy, and the net signature of the ship he has chosen
1763  GET_INT(player_num);
1764  GET_USHORT(net_signature);
1765  PACKET_SET_SIZE();
1766 
1767  objp = multi_get_network_object(net_signature);
1768  if ( objp == NULL ) {
1769  // bogus!!! couldn't find the object -- we cannot connect his -- this is really bad!!!
1770  nprintf(("Network", "Couldn't find ship for ingame joiner %s\n", Net_players[player_num].m_player->callsign));
1771  break;
1772  }
1773  objp->flags |= OF_PLAYER_SHIP;
1774  objp->flags &= ~OF_COULD_BE_PLAYER;
1775 
1776  multi_assign_player_ship( player_num, objp, Ships[objp->instance].ship_info_index );
1777 
1778  break;
1779  }
1780  }
1781 }
1782 
1783 
1784 // --------------------------------------------------------------------------------------------------
1785 // INGAME JOIN FORWARD DEFINITIONS
1786 //
1787 
1789 {
1790  ship_obj *moveup;
1791 
1792  // get the first object on the list
1793  moveup = GET_FIRST(&Ship_obj_list);
1794 
1795  // go through the list and send all ships which are mark as OF_COULD_BE_PLAYER
1796  while(moveup!=END_OF_LIST(&Ship_obj_list)){
1797  //Make sure the object can be a player and is on the same team as this guy
1798  if(Objects[moveup->objnum].flags & OF_COULD_BE_PLAYER && obj_team(&Objects[moveup->objnum]) == p->p_info.team){
1799  // send the update
1801  }
1802 
1803  // move to the next item
1804  moveup = GET_NEXT(moveup);
1805  }
1806 }
1807 
1808 // for now, I guess we'll just send hull and shield % values
1810 {
1812  object *objp;
1813  int idx;
1814  int packet_size = 0;
1815  float f_tmp;
1816 
1818 
1819  // just send net signature, shield and hull percentages
1820  objp = &Objects[sp->objnum];
1821  ADD_USHORT(objp->net_signature);
1822  ADD_UINT(objp->flags);
1823  ADD_INT(objp->n_quadrants);
1824  ADD_FLOAT(objp->hull_strength);
1825 
1826  // shield percentages
1827  for(idx=0; idx<objp->n_quadrants; idx++){
1828  f_tmp = objp->shield_quadrant[idx];
1829  ADD_FLOAT(f_tmp);
1830  }
1831 
1832  multi_io_send_reliable(p, data, packet_size);
1833 }
1834 
1836 {
1837  int offset;
1838  float garbage;
1839  int flags;
1840  int idx;
1841  int n_quadrants;
1842  ushort net_sig;
1843  object *lookup;
1844  float f_tmp;
1845 
1846  offset = HEADER_LENGTH;
1847  // get the net sig for the ship and do a lookup
1848  GET_USHORT(net_sig);
1849  GET_INT(flags);
1850  GET_INT(n_quadrants);
1851 
1852  // get the object
1853  lookup = multi_get_network_object(net_sig);
1854  if(lookup == NULL){
1855  // read in garbage values if we can't find the ship
1856  nprintf(("Network","Got ingame ship update for unknown object\n"));
1857  GET_FLOAT(garbage);
1858  for(idx=0;idx<n_quadrants;idx++){
1859  GET_FLOAT(garbage);
1860  }
1861 
1862  PACKET_SET_SIZE();
1863  return;
1864  }
1865  // otherwise read in the ship values
1866  lookup->flags = flags;
1867  lookup->n_quadrants = n_quadrants;
1868  GET_FLOAT(lookup->hull_strength);
1869  for(idx=0;idx<n_quadrants;idx++){
1870  GET_FLOAT(f_tmp);
1871  lookup->shield_quadrant[idx] = f_tmp;
1872  }
1873 
1874  PACKET_SET_SIZE();
1875 }
void multi_ingame_sync_close()
void set_highlight_action(void(*_user_function)(void))
Definition: button.cpp:375
#define MULTI_INGAME_MAX_SHIP_ICONS
int timestamp(int delta_ms)
Definition: timer.cpp:226
wing Wings[MAX_WINGS]
Definition: ship.cpp:128
#define MY_NET_PLAYER_NUM
Definition: multi.h:127
void obj_set_flags(object *obj, uint new_flags)
Definition: object.cpp:1000
int i
Definition: multi_pxo.cpp:466
fix Missiontime
Definition: systemvars.cpp:19
void multi_ingame_validate_players()
int Multi_ingame_ship_selected
#define GET_DATA(d)
Definition: multimsgs.h:47
void add_XSTR(char *string, int _xstr_id, int _x, int _y, UI_GADGET *_assoc, int _color_type, int _font_id=-1)
Definition: window.cpp:476
int primary_bank_weapons[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:103
#define NETPLAYER_STATE_IN_MISSION
Definition: multi.h:686
UI_BUTTON Multi_ingame_select_button
int Multi_ingame_num_ship_icons
ai_info * Player_ai
Definition: ai.cpp:24
int team
Definition: ship.h:606
#define KEY_DOWN
Definition: key.h:180
char name[NAME_LENGTH]
Definition: weapon.h:322
int num_primary_banks
Definition: ship.h:99
int objnum
Definition: ship.h:537
int Game_mode
Definition: systemvars.cpp:24
void multi_ingame_join_display_avail()
void gr_flip()
Definition: 2d.cpp:2113
void scoring_level_init(scoring_struct *scp)
Definition: scoring.cpp:223
int x
Definition: ui.h:658
void multi_ingame_handle_timeout()
#define NETGAME_STATE_PAUSED
Definition: multi.h:668
void multi_ingame_select_do()
#define INGAME_SHIP_UPDATE_TIME
Definition: multi_ingame.h:77
void multi_ingame_join_check_buttons()
char Game_current_mission_filename[MAX_FILENAME_LEN]
Definition: fredstubs.cpp:26
int obj_team(object *objp)
Definition: object.cpp:1843
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
ship_weapon weapons
Definition: ship.h:658
#define GR_RESIZE_MENU
Definition: 2d.h:684
net_player * Net_player
Definition: multi.cpp:94
#define NETPLAYER_STATE_MISSION_LOADED
Definition: multi.h:679
void multi_ingame_observer_finish()
int y
Definition: ui.h:658
#define MULTI_INGAME_TIME_SECONDS
#define PACKET_SET_SIZE()
Definition: multimsgs.h:57
player * m_player
Definition: multi.h:459
void obj_reset_all_collisions()
Definition: object.cpp:1985
#define MAX_SHIPS
Definition: globals.h:37
#define MULTI_SIG_SHIP
Definition: multiutil.h:32
LOCAL int Ingame_ships_deleted
#define NG_FLAG_INGAME_JOINING_CRITICAL
Definition: multi.h:641
void send_netplayer_update_packet(net_player *pl)
Definition: multimsgs.cpp:2308
#define ADD_DATA(d)
Definition: multimsgs.h:37
void process_ingame_ship_request_packet(ubyte *data, header *hinfo)
#define MULTI_STANDALONE(np)
Definition: multi.h:139
void multi_ingame_scroll_select_down()
Assert(pm!=NULL)
void multi_ts_get_team_and_slot(char *ship_name, int *team_index, int *slot_index, bool mantis2757switch)
#define ADD_STRING(s)
Definition: multimsgs.h:43
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
void multi_obs_create_observer_client()
void multi_ts_get_shipname(char *ship_name, int team, int slot_index)
#define NETINFO_FLAG_OBSERVER
Definition: multi.h:605
void process_ingame_ships_packet(ubyte *data, header *hinfo)
ushort net_signature
Definition: object.h:163
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
int weapon_recharge_index
Definition: ship.h:638
general failure sound for any event
Definition: gamesnd.h:297
void multi_ingame_select_close()
int res
Definition: 2d.h:370
int max_h_unscaled
Definition: 2d.h:361
#define MULTI_END_ERROR_NONE
Definition: multi_endgame.h:43
CButton * team
#define KICK_REASON_BAD_XFER
Definition: multi_kick.h:24
void wl_bash_ship_weapons(ship_weapon *swp, wss_unit *slot)
void multi_ingame_ship_list_process()
void multi_io_send_reliable(net_player *pl, ubyte *data, int len)
Definition: multimsgs.cpp:459
int find_player_id(short player_id)
Definition: multiutil.cpp:465
#define MAX_OBJECTS
Definition: globals.h:83
ushort Multi_ingame_join_sig
ui_button_info Multi_ingame_join_buttons[GR_NUM_RESOLUTIONS][MULTI_INGAME_JOIN_NUM_BUTTONS]
#define GR_MAYBE_CLEAR_RES(bmap)
Definition: 2d.h:639
#define INGAME_SHIP_LIST_EOP
Definition: multi_ingame.h:81
int current_primary_bank
Definition: ship.h:106
int n_quadrants
Definition: object.h:158
void multi_oo_reset_sequencing()
Definition: multi_obj.cpp:1820
virtual void hide(int n)
Definition: gadget.cpp:207
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
void send_netgame_update_packet(net_player *pl)
Definition: multimsgs.cpp:2008
uint flags
Definition: ship.h:644
Definition: ui.h:195
#define GET_ORIENT(d)
Definition: multimsgs.h:54
hull_check orient
Definition: lua.cpp:5049
int flags
Definition: multi.h:463
#define OF_PLAYER_SHIP
Definition: object.h:109
void obj_merge_created_list(void)
Definition: object.cpp:651
object * objp
Definition: lua.cpp:3105
int Multi_ingame_bitmap
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
int current_secondary_bank
Definition: ship.h:107
int max_w_unscaled
Definition: 2d.h:361
#define Int3()
Definition: pstypes.h:292
void multi_ingame_scroll_select_up()
ship * shipp
Definition: lua.cpp:9162
vec3d pos
Definition: object.h:152
int packet_size
Definition: multi_sexp.cpp:41
int bm_release(int handle, int clear_render_targets)
Frees both a bitmap's data and it's associated slot.
Definition: bmpman.cpp:2603
#define INGAME_SHIP_NEXT
Definition: multi_ingame.h:79
#define STANDALONE_SHIP_SIG
Definition: multi.h:738
int game_state
Definition: multi.h:498
void multi_ingame_send_ship_update(net_player *p)
#define GET_VECTOR(d)
Definition: multimsgs.h:55
void hud_shield_show_mini(object *objp, int x_force, int y_force, int x_hull_offset, int y_hull_offset)
Definition: hudshield.cpp:402
#define INGAME_SR_CONFIRM
Definition: multi.h:337
GLenum type
Definition: Gl.h:1492
int multi_xfer_get_status(int handle)
Definition: multi_xfer.cpp:276
int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *keyframe, int can_drop_frames, int dir_type)
Loads a bitmap sequance so we can draw with it.
Definition: bmpman.cpp:1420
int Multi_ingame_num_avail
#define GET_FLOAT(d)
Definition: multimsgs.h:52
#define ADD_INT(d)
Definition: multimsgs.h:40
HWND DWORD code
Definition: vddraw.h:425
#define INGAME_SR_DENY
Definition: multi.h:338
int objnum
Definition: ship.h:1483
int multi_endgame_ending()
void multi_ingame_join_button_pressed(int n)
void send_netplayer_load_packet(net_player *pl)
Definition: multimsgs.cpp:4694
void destroy()
Definition: window.cpp:189
struct is_icon is_icon
#define MAX_PACKET_SIZE
Definition: psnet2.h:34
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define gr_reset_clip
Definition: 2d.h:745
int instance
Definition: object.h:150
void set_mask_bmap(char *fname)
Definition: window.cpp:75
int set_bmaps(char *ani_filename, int nframes=3, int start_frame=1)
Definition: gadget.cpp:71
GLintptr offset
Definition: Glext.h:5497
Definition: player.h:85
void multi_ingame_sync_init()
p_object * mission_parse_get_arrival_ship(const char *name)
Returns the parse object on the ship arrival list associated with the given name. ...
void multi_kick_player(int player_index, int ban, int reason)
Definition: multi_kick.cpp:82
net_player_info p_info
Definition: multi.h:473
#define NUM_ICON_FRAMES
#define MULTI_INGAME_JOIN_NUM_TEXT
void multi_ingame_join_display_ship(object *objp, int y_start)
#define NETINFO_FLAG_AM_MASTER
Definition: multi.h:599
color Color_bright
Definition: alphacolors.cpp:28
unsigned int uint
Definition: pstypes.h:64
int timestamp_until(int stamp)
Definition: timer.cpp:242
#define ADD_FLOAT(d)
Definition: multimsgs.h:42
int state
Definition: multi.h:464
#define nprintf(args)
Definition: pstypes.h:239
#define BUILD_HEADER(t)
Definition: multimsgs.h:36
int primary_bank_ammo[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:121
int flags
Definition: ship.h:1227
#define ADD_UINT(d)
Definition: multimsgs.h:41
int wingnum
Definition: ship.h:623
netgame_info Netgame
Definition: multi.cpp:97
int hotspot
Definition: ui.h:659
int num_secondary_banks
Definition: ship.h:100
int pressed()
Definition: button.cpp:325
float hull_strength
Definition: object.h:160
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
ushort Multi_ingame_ship_sigs[MAX_PLAYERS]
#define INGAME_SHIP_UPDATE
Definition: multi.h:157
#define MULTI_XFER_TIMEDOUT
Definition: multi_xfer.h:27
#define NETINFO_FLAG_MISSION_OK
Definition: multi.h:608
#define GR_640
Definition: 2d.h:652
#define NETINFO_FLAG_INGAME_JOIN
Definition: multi.h:604
is_icon Multi_ingame_ship_icon[MULTI_INGAME_MAX_SHIP_ICONS]
int engine_recharge_index
Definition: ship.h:639
#define SF_PRIMARY_LINKED
Definition: ship.h:458
int secondary_bank_weapons[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:104
int Num_teams
net_player_server_info s_info
Definition: multi.h:472
#define MAX_PLAYERS
Definition: pstypes.h:32
void send_player_settings_packet(net_player *p)
Definition: multimsgs.cpp:5606
void send_jump_into_mission_packet(net_player *pl)
Definition: multimsgs.cpp:4747
char mission_name[NAME_LENGTH+1]
Definition: multi.h:488
#define OF_COULD_BE_PLAYER
Definition: object.h:112
#define ADD_SHORT(d)
Definition: multimsgs.h:38
UI_BUTTON button
Definition: ui.h:660
#define NETINFO_FLAG_RELIABLE_CONNECTED
Definition: multi.h:620
Definition: ship.h:534
int multi_ingame_get_ship_class_icon(int ship_class)
#define SIF_BALLISTIC_PRIMARIES
Definition: ship.h:880
UI_WINDOW Multi_ingame_window
int idx
Definition: multiui.cpp:761
uint respawn_count
Definition: missionparse.h:419
int secondary_bank_ammo[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:134
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
GLclampd n
Definition: Glext.h:7286
void multi_xfer_release_handle(int handle)
Definition: multi_xfer.cpp:339
unsigned char ubyte
Definition: pstypes.h:62
ushort Multi_current_file_checksum
Definition: multi.cpp:150
void send_wss_slots_data_packet(int team_num, int final, net_player *p, int std_request)
Definition: multimsgs.cpp:6154
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
void multi_assign_player_ship(int net_player_num, object *objp, int ship_class)
Definition: multiutil.cpp:681
int objnum
Definition: player.h:124
UI_XSTR Multi_ingame_join_text[GR_NUM_RESOLUTIONS][MULTI_INGAME_JOIN_NUM_TEXT]
#define OBJ_INDEX(objp)
Definition: object.h:235
user_click (mouse selects a control)
Definition: gamesnd.h:305
ship * Player_ship
Definition: ship.cpp:124
matrix orient
Definition: object.h:153
int bmaps[NUM_ICON_FRAMES]
void multi_ingame_unload_icons()
#define OBJ_SHIP
Definition: object.h:32
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
#define GM_STANDALONE_SERVER
Definition: systemvars.h:27
#define MULTI_END_NOTIFY_NONE
Definition: multi_endgame.h:32
GLbitfield flags
Definition: Glext.h:6722
void multi_oo_rate_init(net_player *pl)
Definition: multi_obj.cpp:1696
#define INGAME_JOIN_FLAG_FILE_XFER
Definition: multi_ingame.h:75
#define ADD_USHORT(d)
Definition: multimsgs.h:39
#define INGAME_JOIN_FLAG_SENDING_SETS
Definition: multi_ingame.h:66
#define MULTI_END_ERROR_INGAME_BOGUS
Definition: multi_endgame.h:48
__inline void gr_line(int x1, int y1, int x2, int y2, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:791
#define PROMPT_NONE
Definition: multi_endgame.h:26
void multi_server_update_player_weapons(net_player *pl, ship *shipp)
Definition: multiutil.cpp:2737
GLuint GLfloat * val
Definition: Glext.h:6741
#define INGAME_SR_REQUEST
Definition: multi.h:336
void process_ingame_ship_update_packet(ubyte *data, header *hinfo)
#define INGAME_PLAYER_CHOICE
Definition: multi.h:339
void multi_ingame_select_init()
#define MULTI_END_NOTIFY_INGAME_TIMEOUT
Definition: multi_endgame.h:37
#define MULTI_INGAME_JOIN_NUM_BUTTONS
int bm_load(const char *real_filename)
Loads a bitmap so we can draw with it later.
Definition: bmpman.cpp:1119
int multi_quit_game(int prompt, int notify_code, int err_code, int wsa_error)
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
#define SF_DEPARTING
Definition: ship.h:475
#define INGAME_JOIN_FLAG_SENDING_SHIPS
Definition: multi_ingame.h:69
void obj_delete(int objnum)
Definition: object.cpp:522
void link_hotspot(int num)
Definition: gadget.cpp:50
void create(UI_WINDOW *wnd, char *_text, int _x, int _y, int _w, int _h, int do_repeat=0, int ignore_focus=0)
Definition: button.cpp:26
#define KEY_ESC
Definition: key.h:124
#define NAME_LENGTH
Definition: globals.h:15
#define SF_SECONDARY_DUAL_FIRE
Definition: ship.h:459
void multi_handle_ingame_joiners()
#define UI_XSTR_COLOR_PINK
Definition: ui.h:161
#define MULTI_CONNECTED(np)
Definition: multi.h:136
#define ADD_VECTOR(d)
Definition: multimsgs.h:45
void create(int _x, int _y, int _w, int _h, int _flags, int _f_id=-1)
Definition: window.cpp:140
#define GET_USHORT(d)
Definition: multimsgs.h:49
p_object * mission_parse_get_parse_object(ushort net_signature)
#define ADD_ORIENT(d)
Definition: multimsgs.h:44
#define INGAME_SHIP_REQUEST
Definition: multi.h:158
Definition: ui.h:584
Definition: multi.h:385
screen gr_screen
Definition: 2d.cpp:46
ushort Ingame_ship_signatures[MAX_INGAME_SHIPS]
#define MIJ_JOIN
Definition: ui.h:162
int current_wave
Definition: ship.h:1522
unsigned short ushort
Definition: pstypes.h:63
#define GET_UINT(d)
Definition: multimsgs.h:51
ship_obj Ship_obj_list
Definition: ship.cpp:162
int gr_get_font_height()
Definition: font.cpp:187
int ship_info_index
Definition: ship.h:539
GLfloat GLfloat p
Definition: Glext.h:8373
int HEADER_LENGTH
Definition: multi.cpp:106
#define MULTIPLAYER_MASTER
Definition: multi.h:130
#define INGAME_SHIP_LIST_EOL
Definition: multi_ingame.h:82
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
void common_play_highlight_sound()
Definition: gamesnd.cpp:1151
#define NETPLAYER_STATE_POST_DATA_ACK
Definition: multi.h:697
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
int Multi_current_file_length
Definition: multi.cpp:151
#define timestamp_elapsed(stamp)
Definition: timer.h:102
SCP_vector< float > shield_quadrant
Definition: object.h:159
void get_mouse_pos(int *xx, int *yy)
Definition: gadget.cpp:341
#define PROMPT_CLIENT
Definition: multi_endgame.h:28
short id
Definition: multi.h:390
hull_check pos
Definition: lua.cpp:5050
#define INGAME_PACKET_SLOP
wss_unit Wss_slots_teams[MAX_TVT_TEAMS][MAX_WSS_SLOTS]
color Color_normal
Definition: alphacolors.cpp:28
object * multi_get_network_object(ushort net_signature)
Definition: multiutil.cpp:220
void change_ship_type(int n, int ship_type, int by_sexp)
Definition: ship.cpp:9983
char * filename
Definition: ui.h:657
void multi_ingame_sync_do()
void multi_get_mission_checksum(const char *filename)
Definition: multiutil.cpp:2921
void gr_bitmap(int _x, int _y, int resize_mode)
Definition: 2d.cpp:1303
#define KEY_UP
Definition: key.h:179
void send_ingame_ship_update_packet(net_player *p, ship *sp)
#define UI_XSTR_COLOR_GREEN
Definition: ui.h:160
object * Player_obj
Definition: object.cpp:56
int ship_index
Definition: multi.h:450
#define NETPLAYER_STATE_INGAME_SHIPS
Definition: multi.h:687
#define GET_SHORT(d)
Definition: multimsgs.h:48
uint flags2
Definition: ship.h:645
#define MI_FIELD_X
int ship_class
#define SF_DYING
Definition: ship.h:447
void multi_set_network_signature(ushort signature, int what_kind)
Definition: multiutil.cpp:198
#define GET_INT(d)
Definition: multimsgs.h:50
int bm_unload(int handle, int clear_render_targets, bool nodebug)
Unloads a bitmap's data, but not the bitmap info.
Definition: bmpman.cpp:2890
int ship_name_lookup(const char *name, int inc_players)
Definition: ship.cpp:12900
uint flags
Definition: object.h:151
color Color_bright_blue
Definition: alphacolors.cpp:31
#define MAX_INGAME_SHIPS
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
int Ingame_shipnum
void draw()
Definition: window.cpp:220
struct ui_button_info ui_button_info
void main_hall_stop_music(bool fade)
#define INGAME_JOIN_FLAG_PICK_SHIP
Definition: multi_ingame.h:74
void multi_common_add_text(const char *str, int auto_scroll)
Definition: multiui.cpp:167
#define wp(p)
Definition: modelsinc.h:69
int parse_create_object(p_object *pobjp)
#define LOCAL
Definition: pstypes.h:37
int process(int key_in=-1, int process_mouse=1)
Definition: window.cpp:401
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
void gameseq_post_event(int event)
#define INGAME_JOIN_FLAG_LOADING_MISSION
Definition: multi_ingame.h:68
#define GET_STRING(s)
Definition: multimsgs.h:53
int shield_recharge_index
Definition: ship.h:637
#define MIJ_CANCEL
LOCAL int Ingame_time_left
#define OBJ_GHOST
Definition: object.h:39
#define GR_1024
Definition: 2d.h:653
int flags
Definition: multi.h:495
#define MULTI_XFER_SUCCESS
Definition: multi_xfer.h:24
char ship_name[NAME_LENGTH]
Definition: ship.h:604
void multi_ingame_load_icons()
#define INGAME_JOIN_FLAG_SENDING_POST
Definition: multi_ingame.h:72
void send_post_sync_data_packet(net_player *p, int std_request)
Definition: multimsgs.cpp:5770
#define MI_FIELD_Y
void process_ingame_wings_packet(ubyte *data, header *hinfo)
void mission_hotkey_set_defaults()
void send_ingame_ships_packet(net_player *player)
#define MULTI_XFER_FAIL
Definition: multi_xfer.h:25
#define NET_PLAYER_NUM(np)
Definition: multi.h:126
GLint y
Definition: Gl.h:1505
void multi_obs_create_observer(net_player *pl)
#define strcpy_s(...)
Definition: safe_strings.h:67
void init_multiplayer_stats()
Definition: stats.cpp:308
void send_file_sig_packet(ushort sum_sig, int length_sig)
Definition: multimsgs.cpp:4420
#define NG_FLAG_INGAME_JOINING
Definition: multi.h:640
#define SHIPS_INGAME_PACKET
Definition: multi.h:231
void send_ingame_ship_request_packet(int code, int rdata, net_player *pl)