FS2_Open
Open source remastering of the Freespace 2 engine
multiteamselect.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 
14 #include "network/multi.h"
15 #include "missionui/chatbox.h"
16 #include "gamesnd/gamesnd.h"
17 #include "io/key.h"
18 #include "globalincs/linklist.h"
20 #include "graphics/font.h"
21 #include "network/multiutil.h"
25 #include "missionui/missionbrief.h"
26 #include "network/multimsgs.h"
27 #include "menuui/snazzyui.h"
28 #include "io/mouse.h"
29 #include "popup/popup.h"
30 #include "network/multiui.h"
31 #include "network/multi_endgame.h"
32 #include "globalincs/alphacolors.h"
33 #include "playerman/player.h"
34 #include "ship/ship.h"
35 #include "weapon/weapon.h"
36 #include "object/object.h"
37 #include "parse/parselo.h"
38 #include "mission/missionparse.h"
39 
40 
41 // ------------------------------------------------------------------------------------------------------
42 // TEAM SELECT DEFINES/VARS
43 //
44 
45 // mission screen common data
46 extern int Next_screen;
47 
48 //XSTR:OFF
49 
50 // bitmap defines
51 #define MULTI_TS_PALETTE "InterfacePalette"
52 
54  "TeamSelect", // GR_640
55  "2_TeamSelect" // GR_1024
56 };
57 
59  "TeamSelect-M", // GR_640
60  "2_TeamSelect-M" // GR_1024
61 };
62 
63 // constants for coordinate lookup
64 #define MULTI_TS_X_COORD 0
65 #define MULTI_TS_Y_COORD 1
66 #define MULTI_TS_W_COORD 2
67 #define MULTI_TS_H_COORD 3
68 
69 #define MULTI_TS_NUM_BUTTONS 7
70 #define MULTI_TS_BRIEFING 0 // go to the briefing
71 #define MULTI_TS_SHIP_SELECT 1 // this screen
72 #define MULTI_TS_WEAPON_SELECT 2 // go to the weapon select screen
73 #define MULTI_TS_SHIPS_UP 3 // scroll the ships list up
74 #define MULTI_TS_SHIPS_DOWN 4 // scroll the ships list down
75 #define MULTI_TS_COMMIT 5 // commit
76 #define MULTI_TS_LOCK 6 // lock (free) ship/weapon select
77 
79  { // GR_640
80  ui_button_info("CB_00", 7, 3, 37, 7, 0),
81  ui_button_info("CB_01", 7, 19, 37, 23, 1),
82  ui_button_info("CB_02", 7, 35, 37, 39, 2),
83  ui_button_info("TSB_03", 5, 303, -1, -1, 3),
84  ui_button_info("TSB_04", 5, 454, -1, -1, 4),
85  ui_button_info("TSB_09", 571, 425, 572, 413, 9),
86  ui_button_info("TSB_34", 603, 374, 602, 364, 34)
87  },
88  { // GR_1024
89 
90  ui_button_info("2_CB_00", 12, 5, 59, 12, 0),
91  ui_button_info("2_CB_01", 12, 31, 59, 37, 1),
92  ui_button_info("2_CB_02", 12, 56, 59, 62, 2),
93  ui_button_info("2_TSB_03", 8, 485, -1, -1, 3),
94  ui_button_info("2_TSB_04", 8, 727, -1, -1, 4),
95  ui_button_info("2_TSB_09", 914, 681, 937, 660, 9),
96  ui_button_info("2_TSB_34", 966, 599, 964, 584, 34)
97  },
98 };
99 
100 
101 // players locked ani graphic
102 #define MULTI_TS_NUM_LOCKED_BITMAPS 3
103 
105  { // GR_640
106  "TSB_340000",
107  "TSB_340001",
108  "TSB_340002"
109  },
110  { // GR_1024
111  "2_TSB_340000",
112  "2_TSB_340001",
113  "2_TSB_340002"
114  }
115 };
117 
118 
119 // snazzy menu regions
120 #define TSWING_0_SHIP_0 10
121 #define TSWING_0_SHIP_1 12
122 #define TSWING_0_SHIP_2 14
123 #define TSWING_0_SHIP_3 16
124 #define TSWING_1_SHIP_0 18
125 #define TSWING_1_SHIP_1 20
126 #define TSWING_1_SHIP_2 22
127 #define TSWING_1_SHIP_3 24
128 #define TSWING_2_SHIP_0 26
129 #define TSWING_2_SHIP_1 28
130 #define TSWING_2_SHIP_2 30
131 #define TSWING_2_SHIP_3 32
132 
133 #define TSWING_0_NAME_0 11
134 #define TSWING_0_NAME_1 13
135 #define TSWING_0_NAME_2 15
136 #define TSWING_0_NAME_3 17
137 #define TSWING_1_NAME_0 19
138 #define TSWING_1_NAME_1 21
139 #define TSWING_1_NAME_2 23
140 #define TSWING_1_NAME_3 25
141 #define TSWING_2_NAME_0 27
142 #define TSWING_2_NAME_1 29
143 #define TSWING_2_NAME_2 31
144 #define TSWING_2_NAME_3 33
145 
146 #define TSWING_LIST_0 5
147 #define TSWING_LIST_1 6
148 #define TSWING_LIST_2 7
149 #define TSWING_LIST_3 8
150 
151 #define MULTI_TS_SLOT_LIST 0
152 #define MULTI_TS_PLAYER_LIST 1
153 #define MULTI_TS_AVAIL_LIST 2
154 
155 // interface data
156 #define MULTI_TS_NUM_SNAZZY_REGIONS 28
165 
166 // ship slot data
167 #define MULTI_TS_NUM_SHIP_SLOTS_TEAM 4 // # of ship slots in team v team
168 #define MULTI_TS_FLAG_NONE -2 // never has any ships
169 #define MULTI_TS_FLAG_EMPTY -1 // currently empty
170 
171 static int Multi_ts_slot_icon_coords[MULTI_TS_NUM_SHIP_SLOTS][GR_NUM_RESOLUTIONS][2] = { // x,y
172  { //
173  {128,301}, // GR_640
174  {205,482} // GR_1024
175  },
176  { //
177  {91,347}, // GR_640
178  {146,555} // GR_1024
179  },
180  { //
181  {166,347}, // GR_640
182  {266,555} // GR_1024
183  },
184  { // alpha
185  {128,395}, // GR_640
186  {205,632} // GR_1024
187  },
188  { //
189  {290,301}, // GR_640
190  {464,482} // GR_1024
191  },
192  { //
193  {253,347}, // GR_640
194  {405,555} // GR_1024
195  },
196  { //
197  {328,347}, // GR_640
198  {525,555} // GR_1024
199  },
200  { // beta
201  {290,395}, // GR_640
202  {464,632} // GR_1024
203  },
204  { //
205  {453,301}, // GR_640
206  {725,482} // GR_1024
207  },
208  { //
209  {416,347}, // GR_640
210  {666,555} // GR_1024
211  },
212  { //
213  {491,347}, // GR_640
214  {786,555} // GR_1024
215  },
216  { // gamma
217  {453,395}, // GR_640
218  {725,632} // GR_1024
219  }
220 };
221 
222 static int Multi_ts_slot_text_coords[MULTI_TS_NUM_SHIP_SLOTS][GR_NUM_RESOLUTIONS][3] = { // x,y,width
223  { // alpha
224  {112,330,181-112}, // GR_640
225  {187,517,181-112} // GR_1024
226  },
227  { // alpha
228  {74,377,143-74}, // GR_640
229  {126,592,143-74} // GR_1024
230  },
231  { // alpha
232  {149,377,218-149},// GR_640
233  {248,592,218-149} // GR_1024
234  },
235  { // alpha
236  {112,424,181-112},// GR_640
237  {187,667,181-112} // GR_1024
238  },
239  { // beta
240  {274,330,343-274},// GR_640
241  {446,517,343-274} // GR_1024
242  },
243  { // beta
244  {236,377,305-236},// GR_640
245  {385,592,305-236} // GR_1024
246  },
247  { // beta
248  {311,377,380-311},// GR_640
249  {507,592,380-311} // GR_1024
250  },
251  { // beta
252  {274,424,343-274},// GR_640
253  {446,667,343-274} // GR_1024
254  },
255  { // gamma
256  {437,330,506-437},// GR_640
257  {707,517,506-437} // GR_1024
258  },
259  { // gamma
260  {399,377,468-399},// GR_640
261  {646,592,468-399} // GR_1024
262  },
263  { // gamma
264  {474,377,543-474},// GR_640
265  {768,592,543-474} // GR_1024
266  },
267  { // gamma
268  {437,424,506-437},// GR_640
269  {707,667,506-437} // GR_1024
270  }
271 };
272 
273 // avail ship list data
274 #define MULTI_TS_AVAIL_MAX_DISPLAY 4
275 static int Multi_ts_avail_coords[MULTI_TS_AVAIL_MAX_DISPLAY][GR_NUM_RESOLUTIONS][2] = { // x,y coords
276  { //
277  {23,331}, // GR_640
278  {37,530} // GR_1024
279  },
280  { //
281  {23,361}, // GR_640
282  {37,578} // GR_1024
283  },
284  { //
285  {23,391}, // GR_640
286  {37,626} // GR_1024
287  },
288  { //
289  {23,421}, // GR_640
290  {37,674} // GR_1024
291  }
292 };
293 int Multi_ts_avail_start = 0; // starting index of where we will display the available ships
294 int Multi_ts_avail_count = 0; // the # of available ship classes
295 
296 // ship information stuff
297 #define MULTI_TS_SHIP_INFO_MAX_LINE_LEN 150
298 #define MULTI_TS_SHIP_INFO_MAX_LINES 10
299 #define MULTI_TS_SHIP_INFO_MAX_TEXT (MULTI_TS_SHIP_INFO_MAX_LINE_LEN * MULTI_TS_SHIP_INFO_MAX_LINES)
300 
301 static int Multi_ts_ship_info_coords[GR_NUM_RESOLUTIONS][3] = {
302  { // GR_640
303  33, 150, 387
304  },
305  { // GR_1024
306  53, 240, 618
307  }
308 };
309 
313 
314 // status bar mode
315 static int Multi_ts_status_coords[GR_NUM_RESOLUTIONS][3] = {
316  { // GR_640
317  95, 467, 426
318  },
319  { // GR_1024
320  152, 747, 688
321  }
322 };
323 
325 
326 // carried icon information
333 
334 // selected ship types (for informational purposes)
338 
339 // per-frame mouse hotspot vars
342 
343 // operation types
344 #define TS_GRAB_FROM_LIST 0
345 #define TS_SWAP_LIST_SLOT 1
346 #define TS_SWAP_SLOT_SLOT 2
347 #define TS_DUMP_TO_LIST 3
348 #define TS_SWAP_PLAYER_PLAYER 4
349 #define TS_MOVE_PLAYER 5
350 
351 // packet codes
352 #define TS_CODE_LOCK_TEAM 0 // the specified team's slots are locked
353 #define TS_CODE_PLAYER_UPDATE 1 // a player slot update for the specified team
354 
355 // team data
356 #define MULTI_TS_FLAG_NONE -2 // slot is _always_ empty
357 #define MULTI_TS_FLAG_EMPTY -1 // flag is temporarily empty
358 typedef struct ts_team_data {
359  int multi_ts_objnum[MULTI_TS_NUM_SHIP_SLOTS]; // objnums for all slots in this team
360  net_player *multi_ts_player[MULTI_TS_NUM_SHIP_SLOTS]; // net players corresponding to the same slots
361  int multi_ts_flag[MULTI_TS_NUM_SHIP_SLOTS]; // flags indicating the "status" of a slot
362  int multi_players_locked; // are the players locked into place
363 } ts_team_data;
365 
366 // deleted ship objnums
369 
370 //XSTR:ON
371 
372 // ------------------------------------------------------------------------------------------------------
373 // TEAM SELECT FORWARD DECLARATIONS
374 //
375 
376 // check for button presses
378 
379 // act on a button press
380 void multi_ts_button_pressed(int n);
381 
382 // initialize all screen data, etc
384 
385 // blit all of the icons representing all wings
386 void multi_ts_blit_wings();
387 
388 // blit all of the player callsigns under the correct ships
390 
391 // blit the ships on the avail list
393 
394 // initialize the snazzy menu stuff for dragging ships,players around
395 void multi_ts_init_snazzy();
396 
397 // what type of region the index is (0 == ship avail list, 1 == ship slots, 2 == player slot)
398 int multi_ts_region_type(int region);
399 
400 // convert the region num to a ship slot index
401 int multi_ts_slot_index(int region);
402 
403 // convert the region num to an avail list index
404 int multi_ts_avail_index(int region);
405 
406 // convert the region num to a player slot index
407 int multi_ts_player_index(int region);
408 
409 // blit the status bar
411 
412 // assign the correct players to the correct slots
413 void multi_ts_init_players();
414 
415 // assign the correct objnums to the correct slots
416 void multi_ts_init_objnums();
417 
418 // assign the correct flags to the correct slots
419 void multi_ts_init_flags();
420 
421 // get the proper team and slot index for the given ship name
422 void multi_ts_get_team_and_slot(char *ship_name,int *team_index,int *slot_index, bool mantis2757switch);
423 
424 // handle an available ship scroll down button press
426 
427 // handle an available ship scroll up button press
429 
430 // handle all mouse events (clicking, dragging, and dropping)
431 void multi_ts_handle_mouse();
432 
433 // can the specified player perform the action he is attempting
434 int multi_ts_can_perform(int from_type,int from_index,int to_type,int to_index,int ship_class,int player_index = -1);
435 
436 // determine the kind of drag and drop operation this is
437 int multi_ts_get_dnd_type(int from_type,int from_index,int to_type,int to_index,int player_index = -1);
438 
439 // swap two player positions
440 int multi_ts_swap_player_player(int from_index,int to_index,int *sound,int player_index = -1);
441 
442 // move a player
443 int multi_ts_move_player(int from_index,int to_index,int *sound,int player_index = -1);
444 
445 // get the ship class of the current index in the avail list or -1 if none exists
447 
448 // blit the currently carried icon (if any)
450 
451 // if the (console) player is allowed to grab a player slot at this point
452 int multi_ts_can_grab_player(int slot_index,int player_index = -1);
453 
454 // return the bitmap index into the ships icon array (in ship select) which should be displayed for the given slot
455 int multi_ts_slot_bmap_num(int slot_index);
456 
457 // blit any active ship information text
459 
460 // select the given slot and setup any information, etc
461 void multi_ts_select_ship();
462 
463 // is it ok for this player to commit
465 
466 // return the bitmap index into the ships icon array (in ship select) which should be displayed for the given slot
467 int multi_ts_avail_bmap_num(int slot_index);
468 
469 // set the status bar to reflect the status of wing slots (free or not free). 0 or 1 are valid values for now
471 
472 // check to see that no illegal ship settings have occurred
473 void multi_ts_check_errors();
474 
475 // ------------------------------------------------------------------------------------------------------
476 // TEAM SELECT FUNCTIONS
477 //
478 
479 // initialize the team select screen (always call, even when switching between weapon select, etc)
481 {
482  // if we haven't initialized at all yet, then do it
483  if(!Multi_ts_inited){
485  Multi_ts_inited = 1;
486  }
487 
488  // use the common interface palette
490 
492 
494 }
495 
496 // initialize all critical internal data structures
498 {
499  int idx;
500 
501  // reset timestamps here. they seem to get hosed by the loadinh of the mission file
503 
504  // saying "not allowed to mess with ships"
506 
507  // intialize ship info stuff
511 
512  // initialize carried icon information
515  Multi_ts_clicked_x = 0;
516  Multi_ts_clicked_y = 0;
520 
521  // selected slot information (should be default player ship)
525 
526  // select this ship and setup his info
529  } else {
532 
533  // no ship class selected for information purposes
535  }
536 
537  // deleted ship information
540 
541  // mouse hotspot information
544 
545  // initialize avail ship list data
547 
548  // load the locked button bitmaps bitmaps
549  for(idx=0;idx<MULTI_TS_NUM_LOCKED_BITMAPS;idx++){
552  }
553 
554  // blast the team data clean
555  memset(Multi_ts_team,0,sizeof(ts_team_data) * MULTI_TS_MAX_TVT_TEAMS);
556 
557  // assign the correct players to the correct slots
559 
560  // assign the correct objnums to the correct slots
562 
563  // sync the interface as normal
565 }
566 
567 // do frame for team select
569 {
570  int k = chatbox_process();
571  k = Multi_ts_window.process(k);
572 
573  // process any keypresses
574  switch(k){
575  case KEY_ESC :
578  break;
579 
580  // cycle to the weapon select screen
581  case KEY_TAB :
585  break;
586 
587  case KEY_ENTER|KEY_CTRLED:
588  // multi_ts_commit_pressed();
589  Commit_pressed = 1;
590  break;
591  }
592 
593  // check any button presses
595 
596  // handle all mouse related events
598 
599  // check for errors
601 
602  // draw the background, etc
603  gr_reset_clip();
605  if(Multi_ts_bitmap != -1){
608  }
609  Multi_ts_window.draw();
610 
611  // render all wings
613 
614  // blit all callsigns
616 
617  // blit the ships on the available list
619 
620  // force draw the ship select button
621  Multi_ts_buttons[gr_screen.res][MULTI_TS_SHIP_SELECT].button.draw_forced(2);
622 
623  // force draw the "locked" button if necessary
624  if(multi_ts_is_locked()){
625  Multi_ts_buttons[gr_screen.res][MULTI_TS_LOCK].button.draw_forced(2);
626  } else {
629  Multi_ts_buttons[gr_screen.res][MULTI_TS_LOCK].button.draw_forced(0);
630  } else {
631  Multi_ts_buttons[gr_screen.res][MULTI_TS_LOCK].button.draw();
632  }
633  }
634 
635  // blit any active ship information
637 
638  // blit the status bar
640 
641  // render the chatbox
642  chatbox_render();
643 
644  // render tooltips
645  Multi_ts_window.draw_tooltip();
646 
647  // display the status of the voice system
649 
650  // blit any carried icons
652 
653  // flip the buffer
654  gr_flip();
655 
656  // If the commit button was pressed, do the commit button actions. Done at the end of the
657  // loop since we are a bit special and have to close out in the proper order.
658  if ( Commit_pressed ) {
660  Commit_pressed = 0;
661  }
662 }
663 
664 // close the team select screen (always call, even when switching between weapon select, etc)
666 {
667  int idx;
668 
669  if(!Multi_ts_inited){
670  return;
671  }
672 
673  Multi_ts_inited = 0;
674 
675  // shut down the snazzy menu
677 
678  // unload any bitmaps
680  nprintf(("General","WARNING : could not unload background bitmap %s\n",Multi_ts_bitmap_fname[gr_screen.res]));
681  }
682  for(idx=0;idx<MULTI_TS_NUM_LOCKED_BITMAPS;idx++){
683  if(Multi_ts_locked_bitmaps[idx] != -1){
686  }
687  }
688 
689  // destroy the UI_WINDOW
690  Multi_ts_window.destroy();
691 }
692 
693 // is the given slot disabled for the specified player
694 int multi_ts_disabled_slot(int slot_num, int player_index)
695 {
696  net_player *pl;
697 
698  // get the appropriate net player
699  if(player_index == -1){
700  pl = Net_player;
701  } else {
702  pl = &Net_players[player_index];
703  }
704 
705  // if the player is an observer, its _always_ disabled
706  if(pl->flags & NETINFO_FLAG_OBSERVER){
707  return 1;
708  }
709 
710  // if the flag for this team isn't set to "free" we can't do anything
711  if(!Multi_ts_team[pl->p_info.team].multi_players_locked){
712  return 1;
713  }
714 
715  // if the "leaders" only flag is set
717  // in a team vs. team situation
720  return 0;
721  }
722  }
723  // in a non team vs. team situation
724  else {
725  if(pl->flags & NETINFO_FLAG_GAME_HOST){
726  return 0;
727  }
728  }
729  } else {
730  // in a team vs. team situation
732  // if i'm the team captain I can mess with my own ships as well as those of the ai ships on my team
734  if((Multi_ts_team[pl->p_info.team].multi_ts_player[slot_num] != NULL) && (Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[slot_num]].flags & OF_PLAYER_SHIP) && (slot_num != pl->p_info.ship_index)){
735  return 1;
736  }
737 
738  return 0;
739  }
740  }
741  // in a non team vs. team situation
742  else {
743  // if we're the host, we can our own ship and ai ships
744  if(pl->flags & NETINFO_FLAG_GAME_HOST){
745  // can't grab player ships
746  if((Multi_ts_team[pl->p_info.team].multi_ts_player[slot_num] != NULL) && (Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[slot_num]].flags & OF_PLAYER_SHIP) && (slot_num != pl->p_info.ship_index)){
747  return 1;
748  }
749 
750  return 0;
751  }
752  }
753 
754  // if this is our slot, then we can grab it
755  if(slot_num == pl->p_info.ship_index){
756  return 0;
757  }
758  }
759 
760  return 1;
761 }
762 
763 // is the given slot disabled for the specified player, _and_ it is his ship as well
764 int multi_ts_disabled_high_slot(int slot_index,int player_index)
765 {
766  net_player *pl;
767 
768  // get the appropriate net player
769  if(player_index == -1){
770  pl = Net_player;
771  } else {
772  pl = &Net_players[player_index];
773  }
774 
775  // if this is disabled for him and its also _his_ slot
776  if(multi_ts_disabled_slot(slot_index,player_index) && !Multi_ts_team[pl->p_info.team].multi_players_locked && (slot_index == pl->p_info.ship_index)){
777  return 1;
778  }
779 
780  return 0;
781 }
782 
783 // resynch all display/interface elements based upon all the ship/weapon pool values
785 {
786  int idx;
787 
788  // item 1 - determine how many ship types are available in the ship pool
790  for(idx = 0; idx < static_cast<int>(Ship_info.size()); idx++) {
791  if(Ss_pool[idx] > 0){
793  }
794  }
795 
796  // item 2 - make sure our local Multi_ts_slot_flag array is up to date
798 
799  // item 3 - set/unset any necessary flags in underlying ship select data structures
800  for(idx=0;idx<MAX_WSS_SLOTS;idx++){
801  switch(Multi_ts_team[Net_player->p_info.team].multi_ts_flag[idx]){
802  case MULTI_TS_FLAG_EMPTY :
803  ss_make_slot_empty(idx);
804  break;
805  case MULTI_TS_FLAG_NONE :
806  break;
807  default :
808  ss_make_slot_full(idx);
809  break;
810  }
811  }
812 
813  // item 4 - reset the locked/unlocked status of all ships in the weapon select screen
815 }
816 
818 {
819  int idx,team_index,slot_index,found,player_count,shipnum;
820  char name_lookup[100];
821  object *objp;
822 
823  // set all player ship indices to -1
824  for(idx=0;idx<MAX_PLAYERS;idx++){
827  }
828  }
829 
830  // merge the created object list with the actual object list so we have all available ships
832 
833  // get the # of players currently in the game
834  player_count = multi_num_players();
835 
836  // always assign the host to the wing leader of one of the TVT wings
837  // this is valid for coop games as well because the first starting wing
838  // and the first tvt wing must have the same name
839  memset(name_lookup,0,100);
840 
842  sprintf(name_lookup, "%s 1", TVT_wing_names[Netgame.host->p_info.team]);
843  }
844  else {
845  // To account for cases where <Wingname> 1 is not a player ship
846  for (int i = 0; i < MAX_SHIPS_PER_WING; i++) {
847  wing_bash_ship_name(name_lookup, TVT_wing_names[0], i + 1);
848  if (!stricmp(name_lookup, Player_start_shipname))
849  break;
850  }
851  }
852 
853  shipnum = ship_name_lookup(name_lookup);
854 
855  // if we couldn't find the ship for the host
856  if(shipnum == -1){
857  // Netgame.flags |= NG_FLAG_QUITTING;
859  return;
860  }
861 
862  multi_ts_get_team_and_slot(Ships[shipnum].ship_name,&team_index,&slot_index);
864  Netgame.host->p_info.ship_index = slot_index;
867  Netgame.host->m_player->objnum = Ships[shipnum].objnum;
868 
869  // for each netplayer, try and find a ship
870  objp = GET_FIRST(&obj_used_list);
871  while(objp != END_OF_LIST(&obj_used_list)){
872  // find a valid player ship - ignoring the ship which was assigned to the host
873  if((objp->flags & OF_PLAYER_SHIP) && stricmp(Ships[objp->instance].ship_name,name_lookup)){
874  // determine what team and slot this ship is
875  multi_ts_get_team_and_slot(Ships[objp->instance].ship_name,&team_index,&slot_index, true);
876  Assert((team_index != -1) && (slot_index != -1));
877 
878  // in a team vs. team situation
880  // find a player on this team who needs a ship
881  found = 0;
882  for(idx=0;idx<MAX_PLAYERS;idx++){
883  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_OBSERVER(Net_players[idx]) && (Net_players[idx].p_info.ship_index == -1) && (Net_players[idx].p_info.team == team_index)){
884  found = 1;
885  break;
886  }
887  }
888  }
889  // in a non team vs. team situation
890  else {
891  // find any player on this who needs a ship
892  found = 0;
893  for(idx=0;idx<MAX_PLAYERS;idx++){
894  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_OBSERVER(Net_players[idx]) && (Net_players[idx].p_info.ship_index == -1)){
895  found = 1;
896  break;
897  }
898  }
899  }
900 
901  // if we found a player
902  if(found){
904  Net_players[idx].p_info.ship_index = slot_index;
905  Assert(Net_players[idx].p_info.ship_index >= 0);
908 
909  // decrement the player count
910  player_count--;
911  } else {
912  objp->flags &= ~OF_PLAYER_SHIP;
913  obj_set_flags( objp, objp->flags | OF_COULD_BE_PLAYER );
914  }
915 
916  // if we've assigned all players, we're done
917  if(player_count <= 0){
918  break;
919  }
920  }
921 
922  // move to the next item
923  objp = GET_NEXT(objp);
924  }
925 
926  // go through and change any ships marked as player ships to be COULD_BE_PLAYER
927  if ( objp != END_OF_LIST(&obj_used_list) ) {
928  for ( objp = GET_NEXT(objp); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
929  if ( objp->flags & OF_PLAYER_SHIP ){
930  objp->flags &= ~OF_PLAYER_SHIP;
931  obj_set_flags( objp, objp->flags | OF_COULD_BE_PLAYER );
932  }
933  }
934  }
935 
937  Player_obj = NULL;
938  //Net_player->m_player->objnum = -1;
939  }
940 
941  // check to make sure all players were assigned correctly
942  for(idx=0;idx<MAX_PLAYERS;idx++){
944  // if this guy never got assigned a player ship, there's a mission problem
945  if(Net_players[idx].p_info.ship_index == -1){
946  // Netgame.flags |= NG_FLAG_QUITTING;
948  return;
949  }
950  }
951  }
952 }
953 
954 // delete ships which have been removed from the game, tidy things
956 {
957  int idx,s_idx;
958 
959  // the standalone never went through this screen so he should never call this function!
960  // the standalone and all other clients will have this equivalent function performed whey they receive
961  // the post_sync_data_packet!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
963 
964  // check status of all ships and delete or change ship type as necessary
966  for(idx=0;idx<MULTI_TS_MAX_TVT_TEAMS;idx++){
967  for(s_idx=0;s_idx<MULTI_TS_NUM_SHIP_SLOTS;s_idx++){
968  // otherwise if there's a valid ship in this spot
969  if(Multi_ts_team[idx].multi_ts_flag[s_idx] >= 0){
970  int objnum;
971 
972  // set the ship type appropriately
973  Assert(Wss_slots_teams[idx][s_idx].ship_class >= 0);
974 
975  objnum = Multi_ts_team[idx].multi_ts_objnum[s_idx];
976  change_ship_type(Objects[objnum].instance,Wss_slots_teams[idx][s_idx].ship_class);
977 
978  // set the ship weapons correctly
979  wl_update_ship_weapons(objnum,&Wss_slots_teams[idx][s_idx]);
980 
981  // assign ts_index of the ship to point to the proper Wss_slots slot
982  Ships[Objects[objnum].instance].ts_index = s_idx;
983  } else if(Multi_ts_team[idx].multi_ts_flag[s_idx] == MULTI_TS_FLAG_EMPTY){
984  Assert(Multi_ts_team[idx].multi_ts_objnum[s_idx] >= 0);
985 
986  // mark the object as having been deleted
988 
989  // delete the ship
992  ship_wing_cleanup(Objects[Multi_ts_deleted_objnums[Multi_ts_num_deleted]].instance,&Wings[Ships[Objects[Multi_ts_team[idx].multi_ts_objnum[s_idx]].instance].wingnum]);
993 
994  // increment the # of ships deleted
995  Multi_ts_num_deleted++;
996  }
997  }
998  }
999 }
1000 
1001 // do any necessary processing for players who have left the game
1003 {
1004  int idx,s_idx;
1005 
1006  // find the player
1007  for(idx=0;idx<MULTI_TS_MAX_TVT_TEAMS;idx++){
1008  for(s_idx=0;s_idx<MULTI_TS_NUM_SHIP_SLOTS;s_idx++){
1009  // if we found him, clear his player slot and set his object back to being OF_COULD_BE_PLAYER
1010  if((Multi_ts_team[idx].multi_ts_player[s_idx] != NULL) && !MULTI_CONNECTED((*Multi_ts_team[idx].multi_ts_player[s_idx]))){
1011  Assert(Multi_ts_team[idx].multi_ts_objnum[s_idx] != -1);
1012  Multi_ts_team[idx].multi_ts_player[s_idx] = NULL;
1013  Objects[Multi_ts_team[idx].multi_ts_objnum[s_idx]].flags &= ~(OF_PLAYER_SHIP);
1014  obj_set_flags( &Objects[Multi_ts_team[idx].multi_ts_objnum[s_idx]], Objects[Multi_ts_team[idx].multi_ts_objnum[s_idx]].flags | OF_COULD_BE_PLAYER);
1015  }
1016  }
1017  }
1018 }
1019 
1020 // set the status bar to reflect the status of wing slots (free or not free). 0 or 1 are valid values for now
1022 {
1024 }
1025 
1026 // the "lock" button has been pressed
1028 {
1029  // do nothing if the button has already been pressed
1030  if(multi_ts_is_locked()){
1032  return;
1033  }
1034 
1037  } else {
1039  }
1041 
1042  // send a final player slot update packet
1044  Multi_ts_team[Net_player->p_info.team].multi_players_locked = 1;
1045 
1046  // sync interface stuff
1050 
1051  // disable this button now
1052  Multi_ts_buttons[gr_screen.res][MULTI_TS_LOCK].button.disable();
1053 }
1054 
1055 // if i'm "locked"
1057 {
1058  return Multi_ts_team[Net_player->p_info.team].multi_players_locked;
1059 }
1060 
1061 // show a popup saying "only host and team captains can modify, etc, etc"
1063 {
1064 /*
1065  // if this is because the "host modifies" option is set
1066  if((Netgame.options.flags & MSO_FLAG_SS_LEADERS) && !(Net_player->flags & NETINFO_FLAG_GAME_HOST) && !(Net_player->flags & NETINFO_FLAG_TEAM_CAPTAIN)){
1067  multi_ts_host_only_popup();
1068  }
1069 
1070  if(Netgame.type == NG_TYPE_TEAM){
1071  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,"Only team captains may modify ships and weapons in this game");
1072  } else {
1073  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,"Only the host may modify ships and weapons in this game");
1074  }
1075  */
1076 }
1077 
1078 
1079 // ------------------------------------------------------------------------------------------------------
1080 // TEAM SELECT FORWARD DEFINITIONS
1081 //
1082 
1083 // check for button presses
1085 {
1086  int idx;
1087  for(idx=0;idx<MULTI_TS_NUM_BUTTONS;idx++){
1088  // we only really need to check for one button pressed at a time, so we can break after
1089  // finding one.
1090  if(Multi_ts_buttons[gr_screen.res][idx].button.pressed()){
1092  break;
1093  }
1094  }
1095 }
1096 
1097 // act on a button press
1099 {
1100  switch(n){
1101  // back to the briefing screen
1102  case MULTI_TS_BRIEFING :
1106  break;
1107  // already on this screen
1108  case MULTI_TS_SHIP_SELECT:
1110  break;
1111  // back to the weapon select screen
1116  break;
1117  // scroll the available ships list down
1118  case MULTI_TS_SHIPS_DOWN:
1120  break;
1121  // scroll the available ships list up
1122  case MULTI_TS_SHIPS_UP:
1124  break;
1125  // free ship/weapon select
1126  case MULTI_TS_LOCK:
1128  // the "lock" button has been pressed
1130 
1131  // disable the button if it is now locked
1132  if(multi_ts_is_locked()){
1133  Multi_ts_buttons[gr_screen.res][MULTI_TS_LOCK].button.disable();
1134  }
1135  break;
1136  // commit button
1137  case MULTI_TS_COMMIT :
1138  // multi_ts_commit_pressed();
1139  Commit_pressed = 1;
1140  break;
1141  default :
1143  break;
1144  }
1145 }
1146 
1147 // initialize all screen data, etc
1149 {
1150  int idx;
1151 
1152  // create the interface window
1153  Multi_ts_window.create(0,0,gr_screen.max_w_unscaled,gr_screen.max_h_unscaled,0);
1155 
1156  // load the background bitmap
1158 
1159  if(Multi_ts_bitmap < 0){
1160  // we failed to load the bitmap - this is very bad
1161  Int3();
1162  }
1163 
1164  // create the interface buttons
1165  for(idx=0;idx<MULTI_TS_NUM_BUTTONS;idx++){
1166  // create the object
1167  if((idx == MULTI_TS_SHIPS_UP) || (idx == MULTI_TS_SHIPS_DOWN)){
1168  Multi_ts_buttons[gr_screen.res][idx].button.create(&Multi_ts_window, "", Multi_ts_buttons[gr_screen.res][idx].x, Multi_ts_buttons[gr_screen.res][idx].y, 1, 1, 1, 1);
1169  } else {
1170  Multi_ts_buttons[gr_screen.res][idx].button.create(&Multi_ts_window, "", Multi_ts_buttons[gr_screen.res][idx].x, Multi_ts_buttons[gr_screen.res][idx].y, 1, 1, 0, 1);
1171  }
1172 
1173  // set the sound to play when highlighted
1175 
1176  // set the ani for the button
1177  Multi_ts_buttons[gr_screen.res][idx].button.set_bmaps(Multi_ts_buttons[gr_screen.res][idx].filename);
1178 
1179  // set the hotspot
1180  Multi_ts_buttons[gr_screen.res][idx].button.link_hotspot(Multi_ts_buttons[gr_screen.res][idx].hotspot);
1181  }
1182 
1183  // add some text
1184  Multi_ts_window.add_XSTR("Briefing", 765, Multi_ts_buttons[gr_screen.res][MULTI_TS_BRIEFING].xt, Multi_ts_buttons[gr_screen.res][MULTI_TS_BRIEFING].yt, &Multi_ts_buttons[gr_screen.res][MULTI_TS_BRIEFING].button, UI_XSTR_COLOR_GREEN);
1185  Multi_ts_window.add_XSTR("Ship Selection", 1067, Multi_ts_buttons[gr_screen.res][MULTI_TS_SHIP_SELECT].xt, Multi_ts_buttons[gr_screen.res][MULTI_TS_SHIP_SELECT].yt, &Multi_ts_buttons[gr_screen.res][MULTI_TS_SHIP_SELECT].button, UI_XSTR_COLOR_GREEN);
1186  Multi_ts_window.add_XSTR("Weapon Loadout", 1068, Multi_ts_buttons[gr_screen.res][MULTI_TS_WEAPON_SELECT].xt, Multi_ts_buttons[gr_screen.res][MULTI_TS_WEAPON_SELECT].yt, &Multi_ts_buttons[gr_screen.res][MULTI_TS_WEAPON_SELECT].button, UI_XSTR_COLOR_GREEN);
1187  Multi_ts_window.add_XSTR("Commit", 1062, Multi_ts_buttons[gr_screen.res][MULTI_TS_COMMIT].xt, Multi_ts_buttons[gr_screen.res][MULTI_TS_COMMIT].yt, &Multi_ts_buttons[gr_screen.res][MULTI_TS_COMMIT].button, UI_XSTR_COLOR_PINK);
1188  Multi_ts_window.add_XSTR("Lock", 1270, Multi_ts_buttons[gr_screen.res][MULTI_TS_LOCK].xt, Multi_ts_buttons[gr_screen.res][MULTI_TS_LOCK].yt, &Multi_ts_buttons[gr_screen.res][MULTI_TS_LOCK].button, UI_XSTR_COLOR_GREEN);
1189 
1190 // Multi_ts_window.add_XSTR("Help", 928, Multi_ts_buttons[Current_screen-1][gr_screen.res][COMMON_HELP_BUTTON].xt, Multi_ts_buttons[Current_screen-1][gr_screen.res][COMMON_HELP_BUTTON].yt, &Multi_ts_buttons[Current_screen-1][gr_screen.res][COMMON_HELP_BUTTON].button, UI_XSTR_COLOR_GREEN);
1191 // Multi_ts_window.add_XSTR("Options", 1036, Multi_ts_buttons[Current_screen-1][gr_screen.res][COMMON_OPTIONS_BUTTON].xt, Multi_ts_buttons[Current_screen-1][gr_screen.res][COMMON_OPTIONS_BUTTON].yt, &Multi_ts_buttons[Current_screen-1][gr_screen.res][COMMON_OPTIONS_BUTTON].button, UI_XSTR_COLOR_GREEN);
1192 
1193 
1194 
1195  // make the ship scrolling lists
1196 
1197  // if we're not the host of the game (or a tema captain in team vs. team mode), disable the lock button
1200  Multi_ts_buttons[gr_screen.res][MULTI_TS_LOCK].button.disable();
1201  }
1202  } else {
1204  Multi_ts_buttons[gr_screen.res][MULTI_TS_LOCK].button.disable();
1205  }
1206  }
1207 
1208  // initialize the snazzy menu stuff (for grabbing ships, names, etc)
1210 
1211  // create the chatbox (again, should not be necessary at this point)
1212  chatbox_create();
1213 
1214  // sync the interface as normal
1216 }
1217 
1218 // blit all of the icons representing all wings
1220 {
1221  int idx;
1222 
1223  // blit them all blindly for now
1224  for(idx=0;idx<MAX_WSS_SLOTS;idx++){
1225  // if this ship doesn't exist, then continue
1226  if(Multi_ts_team[Net_player->p_info.team].multi_ts_flag[idx] == MULTI_TS_FLAG_NONE){
1227  continue;
1228  }
1229 
1230  // otherwise blit the ship icon or the "empty" icon
1231  if(Multi_ts_team[Net_player->p_info.team].multi_ts_flag[idx] == MULTI_TS_FLAG_EMPTY){
1232  ss_blit_ship_icon(Multi_ts_slot_icon_coords[idx][gr_screen.res][MULTI_TS_X_COORD],Multi_ts_slot_icon_coords[idx][gr_screen.res][MULTI_TS_Y_COORD],-1,0);
1233  } else {
1234  ss_blit_ship_icon(Multi_ts_slot_icon_coords[idx][gr_screen.res][MULTI_TS_X_COORD],Multi_ts_slot_icon_coords[idx][gr_screen.res][MULTI_TS_Y_COORD],Wss_slots[idx].ship_class,multi_ts_slot_bmap_num(idx));
1235 
1236  // if this is a team vs team game, and the slot is occupised by a team captain, put a c there
1237  if((Netgame.type_flags & NG_TYPE_TEAM) && (Multi_ts_team[Net_player->p_info.team].multi_ts_player[idx] != NULL) && (Multi_ts_team[Net_player->p_info.team].multi_ts_player[idx]->flags & NETINFO_FLAG_TEAM_CAPTAIN)){
1239  gr_string(Multi_ts_slot_icon_coords[idx][gr_screen.res][MULTI_TS_X_COORD] - 5,Multi_ts_slot_icon_coords[idx][gr_screen.res][MULTI_TS_Y_COORD] - 5, XSTR("C",737), GR_RESIZE_MENU); // [[ Team captain ]]
1240  }
1241  }
1242  }
1243 }
1244 
1245 // blit all of the player callsigns under the correct ships
1247 {
1248  int idx,callsign_w;
1249  char callsign[CALLSIGN_LEN+2];
1250  p_object *pobj;
1251 
1252  // blit them all blindly for now
1253  for(idx=0;idx<MAX_WSS_SLOTS;idx++){
1254  // if this ship doesn't exist, then continue
1255  if(Multi_ts_team[Net_player->p_info.team].multi_ts_flag[idx] == MULTI_TS_FLAG_NONE){
1256  continue;
1257  }
1258 
1259  // if there is a player in the slot
1260  if(Multi_ts_team[Net_player->p_info.team].multi_ts_player[idx] != NULL){
1261  // make sure the string fits
1262  strcpy_s(callsign,Multi_ts_team[Net_player->p_info.team].multi_ts_player[idx]->m_player->callsign);
1263  } else {
1264  // determine if this is a locked AI ship
1266  if((pobj == NULL) || !(pobj->flags & OF_PLAYER_SHIP)){
1267  strcpy_s(callsign, NOX("<"));
1268  strcat_s(callsign, XSTR("AI",738)); // [[ Artificial Intellegence ]]
1269  strcat_s(callsign, NOX(">"));
1270  } else {
1271  strcpy_s(callsign, XSTR("AI",738)); // [[ Artificial Intellegence ]]
1272  }
1273  }
1274 
1275  gr_force_fit_string(callsign, CALLSIGN_LEN, Multi_ts_slot_text_coords[idx][gr_screen.res][MULTI_TS_W_COORD]);
1276 
1277  // get the final length
1278  gr_get_string_size(&callsign_w, NULL, callsign);
1279 
1280  // blit the string
1281  if((Multi_ts_hotspot_type == MULTI_TS_PLAYER_LIST) && (Multi_ts_hotspot_index == idx) && (Multi_ts_team[Net_player->p_info.team].multi_ts_player[idx] != NULL)){
1283  } else {
1285  }
1286  gr_string(Multi_ts_slot_text_coords[idx][gr_screen.res][MULTI_TS_X_COORD] + ((Multi_ts_slot_text_coords[idx][gr_screen.res][MULTI_TS_W_COORD] - callsign_w)/2),Multi_ts_slot_text_coords[idx][gr_screen.res][MULTI_TS_Y_COORD],callsign,GR_RESIZE_MENU);
1287  }
1288 }
1289 
1290 // blit the ships on the avail list
1292 {
1293  int display_count,ship_count,idx;
1294  char count[6];
1295 
1296  // blit the availability of all ship counts
1297  display_count = 0;
1298  ship_count = 0;
1299  for(idx = 0; idx < static_cast<int>(Ship_info.size()); idx++) {
1300  if(Ss_pool[idx] > 0){
1301  // if our starting display index is after this, then skip it
1302  if(ship_count < Multi_ts_avail_start){
1303  ship_count++;
1304  } else {
1305  // blit the icon
1306  ss_blit_ship_icon(Multi_ts_avail_coords[display_count][gr_screen.res][MULTI_TS_X_COORD],Multi_ts_avail_coords[display_count][gr_screen.res][MULTI_TS_Y_COORD],idx,multi_ts_avail_bmap_num(display_count));
1307 
1308  // blit the ship count available
1309  sprintf(count,"%d",Ss_pool[idx]);
1311  gr_string(Multi_ts_avail_coords[display_count][gr_screen.res][MULTI_TS_X_COORD] - 20,Multi_ts_avail_coords[display_count][gr_screen.res][MULTI_TS_Y_COORD],count,GR_RESIZE_MENU);
1312 
1313  // increment the counts
1314  display_count++;
1315  ship_count++;
1316  }
1317  }
1318 
1319  // if we've reached the max amount we can display, then stop
1320  if(display_count >= MULTI_TS_AVAIL_MAX_DISPLAY){
1321  return;
1322  }
1323  }
1324 }
1325 
1326 // initialize the snazzy menu stuff for dragging ships,players around
1328 {
1329  // initialize the snazzy menu
1330  snazzy_menu_init();
1331 
1332  // blast the data
1334  memset(Multi_ts_region,0,sizeof(MENU_REGION) * MULTI_TS_NUM_SNAZZY_REGIONS);
1335 
1336  // get a pointer to the mask bitmap data
1338 
1339  // add the wing slots information
1340  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_0_SHIP_0, 0);
1341  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_0_SHIP_1, 0);
1342  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_0_SHIP_2, 0);
1343  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_0_SHIP_3, 0);
1344  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_1_SHIP_0, 0);
1345  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_1_SHIP_1, 0);
1346  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_1_SHIP_2, 0);
1347  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_1_SHIP_3, 0);
1348  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_2_SHIP_0, 0);
1349  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_2_SHIP_1, 0);
1350  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_2_SHIP_2, 0);
1351  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_2_SHIP_3, 0);
1352 
1353  // add the name slots information
1354  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_0_NAME_0, 0);
1355  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_0_NAME_1, 0);
1356  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_0_NAME_2, 0);
1357  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_0_NAME_3, 0);
1358  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_1_NAME_0, 0);
1359  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_1_NAME_1, 0);
1360  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_1_NAME_2, 0);
1361  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_1_NAME_3, 0);
1362  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_2_NAME_0, 0);
1363  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_2_NAME_1, 0);
1364  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_2_NAME_2, 0);
1365  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_2_NAME_3, 0);
1366 
1367  // add the available ships region
1368  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_LIST_0, 0);
1369  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_LIST_1, 0);
1370  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_LIST_2, 0);
1371  snazzy_menu_add_region(&Multi_ts_region[Multi_ts_snazzy_regions++], "", TSWING_LIST_3, 0);
1372 }
1373 
1374 // what type of region the index is (0 == ship avail list, 1 == ship slots, 2 == player slot)
1375 int multi_ts_region_type(int region)
1376 {
1377  if((region == TSWING_0_SHIP_0) || (region == TSWING_0_SHIP_1) || (region == TSWING_0_SHIP_2) || (region == TSWING_0_SHIP_3) ||
1378  (region == TSWING_1_SHIP_0) || (region == TSWING_1_SHIP_1) || (region == TSWING_1_SHIP_2) || (region == TSWING_1_SHIP_3) ||
1379  (region == TSWING_2_SHIP_0) || (region == TSWING_2_SHIP_1) || (region == TSWING_2_SHIP_2) || (region == TSWING_2_SHIP_3) ){
1380  return MULTI_TS_SLOT_LIST;
1381  }
1382 
1383  if((region == TSWING_0_NAME_0) || (region == TSWING_0_NAME_1) || (region == TSWING_0_NAME_2) || (region == TSWING_0_NAME_3) ||
1384  (region == TSWING_1_NAME_0) || (region == TSWING_1_NAME_1) || (region == TSWING_1_NAME_2) || (region == TSWING_1_NAME_3) ||
1385  (region == TSWING_2_NAME_0) || (region == TSWING_2_NAME_1) || (region == TSWING_2_NAME_2) || (region == TSWING_2_NAME_3) ){
1386  return MULTI_TS_PLAYER_LIST;
1387  }
1388 
1389  if((region == TSWING_LIST_0) || (region == TSWING_LIST_1) || (region == TSWING_LIST_2) || (region == TSWING_LIST_3)){
1390  return MULTI_TS_AVAIL_LIST;
1391  }
1392 
1393  return -1;
1394 }
1395 
1396 // convert the region num to a ship slot index
1397 int multi_ts_slot_index(int region)
1398 {
1399  switch(region){
1400  case TSWING_0_SHIP_0:
1401  return 0;
1402  case TSWING_0_SHIP_1:
1403  return 1;
1404  case TSWING_0_SHIP_2:
1405  return 2;
1406  case TSWING_0_SHIP_3:
1407  return 3;
1408  case TSWING_1_SHIP_0:
1409  return 4;
1410  case TSWING_1_SHIP_1:
1411  return 5;
1412  case TSWING_1_SHIP_2:
1413  return 6;
1414  case TSWING_1_SHIP_3:
1415  return 7;
1416  case TSWING_2_SHIP_0:
1417  return 8;
1418  case TSWING_2_SHIP_1:
1419  return 9;
1420  case TSWING_2_SHIP_2:
1421  return 10;
1422  case TSWING_2_SHIP_3:
1423  return 11;
1424  }
1425 
1426  return -1;
1427 }
1428 
1429 // convert the region num to an avail list index (starting from absolute 0)
1430 int multi_ts_avail_index(int region)
1431 {
1432  switch(region){
1433  case TSWING_LIST_0:
1434  return 0;
1435  case TSWING_LIST_1:
1436  return 1;
1437  case TSWING_LIST_2:
1438  return 2;
1439  case TSWING_LIST_3:
1440  return 3;
1441  }
1442 
1443  return -1;
1444 }
1445 
1446 // convert the region num to a player slot index
1447 int multi_ts_player_index(int region)
1448 {
1449  switch(region){
1450  case TSWING_0_NAME_0:
1451  return 0;
1452  case TSWING_0_NAME_1:
1453  return 1;
1454  case TSWING_0_NAME_2:
1455  return 2;
1456  case TSWING_0_NAME_3:
1457  return 3;
1458  case TSWING_1_NAME_0:
1459  return 4;
1460  case TSWING_1_NAME_1:
1461  return 5;
1462  case TSWING_1_NAME_2:
1463  return 6;
1464  case TSWING_1_NAME_3:
1465  return 7;
1466  case TSWING_2_NAME_0:
1467  return 8;
1468  case TSWING_2_NAME_1:
1469  return 9;
1470  case TSWING_2_NAME_2:
1471  return 10;
1472  case TSWING_2_NAME_3:
1473  return 11;
1474  }
1475 
1476  return -1;
1477 }
1478 
1479 // blit any active ship information text
1481 {
1482  int y_start, line_height;
1483  ship_info *sip;
1484  char str[100];
1485 
1486  // if we don't have a valid ship selected, do nothing
1487  if(Multi_ts_select_ship_class == -1){
1488  return;
1489  }
1490 
1491  // get the ship class
1493 
1494  // starting line
1495  y_start = Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_Y_COORD];
1496 
1497  line_height = gr_get_font_height() + 1;
1498 
1499  memset(str,0,100);
1500 
1501  // blit the ship class (name)
1503  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD], y_start, XSTR("Class",739), GR_RESIZE_MENU);
1504  if(strlen((sip->alt_name[0]) ? sip->alt_name : sip->name)){
1506 
1507  // Goober5000
1508  char temp[NAME_LENGTH];
1509  strcpy_s(temp, (sip->alt_name[0]) ? sip->alt_name : sip->name);
1511 
1512  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD] + 150, y_start, temp, GR_RESIZE_MENU);
1513  }
1514  y_start += line_height;
1515 
1516  // blit the ship type
1518  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD], y_start, XSTR("Type",740), GR_RESIZE_MENU);
1519  if((sip->type_str != NULL) && strlen(sip->type_str)){
1521  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD] + 150, y_start, sip->type_str, GR_RESIZE_MENU);
1522  }
1523  y_start += line_height;
1524 
1525  // blit the ship length
1527  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD], y_start, XSTR("Length",741), GR_RESIZE_MENU);
1528  if((sip->ship_length != NULL) && strlen(sip->ship_length)){
1530  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD] + 150, y_start, sip->ship_length, GR_RESIZE_MENU);
1531  }
1532  y_start += line_height;
1533 
1534  // blit the max velocity
1536  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD], y_start, XSTR("Max Velocity",742), GR_RESIZE_MENU);
1537  sprintf(str, XSTR("%d m/s",743),(int)sip->max_vel.xyz.z);
1539  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD] + 150, y_start,str,GR_RESIZE_MENU);
1540  y_start += line_height;
1541 
1542  // blit the maneuverability
1544  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD], y_start, XSTR("Maneuverability",744), GR_RESIZE_MENU);
1545  if((sip->maneuverability_str != NULL) && strlen(sip->maneuverability_str)){
1547  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD] + 150, y_start, sip->maneuverability_str, GR_RESIZE_MENU);
1548  }
1549  y_start += line_height;
1550 
1551  // blit the armor
1553  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD], y_start, XSTR("Armor",745), GR_RESIZE_MENU);
1554  if((sip->armor_str != NULL) && strlen(sip->armor_str)){
1556  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD] + 150, y_start, sip->armor_str, GR_RESIZE_MENU);
1557  }
1558  y_start += line_height;
1559 
1560  // blit the gun mounts
1562  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD], y_start, XSTR("Gun Mounts",746), GR_RESIZE_MENU);
1563  if((sip->gun_mounts != NULL) && strlen(sip->gun_mounts)){
1565  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD] + 150, y_start, sip->gun_mounts, GR_RESIZE_MENU);
1566  }
1567  y_start += line_height;
1568 
1569  // blit the missile banke
1571  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD], y_start, XSTR("Missile Banks",747), GR_RESIZE_MENU);
1572  if((sip->missile_banks != NULL) && strlen(sip->missile_banks)){
1574  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD] + 150, y_start, sip->missile_banks, GR_RESIZE_MENU);
1575  }
1576  y_start += line_height;
1577 
1578  // blit the manufacturer
1580  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD], y_start, XSTR("Manufacturer",748), GR_RESIZE_MENU);
1581  if((sip->manufacturer_str != NULL) && strlen(sip->manufacturer_str)){
1583  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD] + 150, y_start, sip->manufacturer_str, GR_RESIZE_MENU);
1584  }
1585  y_start += line_height;
1586 
1587  // blit the _short_ text description
1588 
1592  gr_string(Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_X_COORD], y_start, Multi_ts_ship_info_lines[idx], GR_RESIZE_MENU);
1593  y_start += line_height;
1594  }
1595 
1596 }
1597 
1598 
1599 // blit the status bar
1601 {
1602  char text[50];
1603  int text_w;
1604  int blit = 0;
1605 
1606  // mode specific text
1607  switch(Multi_ts_status_bar_mode){
1608  case 0 :
1609  strcpy_s(text, XSTR("Ships/Weapons Locked",749));
1610  blit = 1;
1611  break;
1612  case 1 :
1613  strcpy_s(text, XSTR("Ships/Weapons Are Now Free",750));
1614  blit = 1;
1615  break;
1616  }
1617 
1618  // if we should be blitting
1619  if(blit){
1620  gr_get_string_size(&text_w,NULL,text);
1622  gr_string(Multi_ts_status_coords[gr_screen.res][MULTI_TS_X_COORD] + ((Multi_ts_status_coords[gr_screen.res][MULTI_TS_W_COORD] - text_w)/2),Multi_ts_status_coords[gr_screen.res][MULTI_TS_Y_COORD],text,GR_RESIZE_MENU);
1623  }
1624 }
1625 
1626 // assign the correct players to the correct slots
1628 {
1629  int idx;
1630 
1631  // if i'm an observer, i have no ship
1634  }
1635 
1636  // initialize all players and observer
1637  for(idx=0;idx<MAX_PLAYERS;idx++){
1639  if(MULTI_OBSERVER(Net_players[idx])){
1641  } else {
1643  }
1644  }
1645  }
1646 }
1647 
1648 // assign the correct objnums to the correct slots
1650 {
1651  int idx,s_idx,team_index,slot_index;
1652  object *objp;
1653 
1654  // zero out the indices
1655  for(idx=0;idx<MULTI_TS_MAX_TVT_TEAMS;idx++){
1656  for(s_idx=0;s_idx<MULTI_TS_NUM_SHIP_SLOTS;s_idx++){
1657  Multi_ts_team[idx].multi_ts_objnum[s_idx] = -1;
1658  }
1659  }
1660 
1661  // set all the objnums
1662  objp = GET_FIRST(&obj_used_list);
1663  while(objp != END_OF_LIST(&obj_used_list)){
1664  // if its a ship, get its slot index (if any)
1665  if(objp->type == OBJ_SHIP){
1666  multi_ts_get_team_and_slot(Ships[objp->instance].ship_name,&team_index,&slot_index);
1667  if((slot_index != -1) && (team_index != -1)){
1668  Multi_ts_team[team_index].multi_ts_objnum[slot_index] = Ships[objp->instance].objnum;
1669  }
1670  }
1671 
1672  objp = GET_NEXT(objp);
1673  }
1674 }
1675 
1676 bool multi_ts_validate_ship(char *shipname, char *wingname)
1677 {
1678  int wing_number, wing_idx;
1679 
1680  // check name isn't too short to be valid
1681  if (strlen(shipname) < (strlen (wingname) + 2) ) {
1682  return false;
1683  }
1684 
1685  wing_idx = wing_lookup(wingname);
1686  Assert (wing_idx >= 0 && wing_idx < MAX_WINGS);
1687  wing_number = atoi(shipname+strlen(wingname));
1688 
1689  if (wing_number > 0 && wing_number <= Wings[wing_idx].wave_count) {
1690  return true;
1691  }
1692 
1693  return false;
1694 }
1695 
1696 // get the proper team and slot index for the given ship name
1697 void multi_ts_get_team_and_slot(char *ship_name,int *team_index,int *slot_index, bool mantis2757switch)
1698 {
1699  int idx;
1700 
1701  // set the return values to default values
1702  *team_index = -1;
1703  *slot_index = -1;
1704 
1705  // if we're in team vs. team mode
1708  for (idx = 0; idx < MAX_TVT_WINGS; idx++) {
1709  // get team (wing)
1710  if ( !strnicmp(ship_name, TVT_wing_names[idx], strlen(TVT_wing_names[idx])) && multi_ts_validate_ship(ship_name, TVT_wing_names[idx]) ) {
1711  *team_index = idx;
1712  *slot_index = (ship_name[strlen(ship_name)-1] - '1');
1713 
1714  // just Assert(), if this is wrong then we're pretty much screwed either way
1715  Assert( (*slot_index >= 0) && (*slot_index < MAX_WSS_SLOTS) );
1716  }
1717  }
1718  }
1719  // if we're _not_ in team vs. team mode
1720  else {
1721  int wing_index, ship;
1722  for (idx = 0; idx < MAX_STARTING_WINGS; idx++) {
1723  // get wing
1724  if ( !strnicmp(ship_name, Starting_wing_names[idx], strlen(Starting_wing_names[idx])) && multi_ts_validate_ship(ship_name, Starting_wing_names[idx]) ) {
1725  wing_index = idx;
1726  ship = (ship_name[strlen(ship_name)-1] - '1');
1727 
1728  // just Assert(), if this is wrong then we're pretty much screwed either way
1729  Assert( (ship >= 0) && (ship < MULTI_TS_NUM_SHIP_SLOTS_TEAM) );
1730 
1731  // team is 0, slot is the starting slot for all ships
1732  *team_index = 0;
1733  *slot_index = wing_index * MULTI_TS_NUM_SHIP_SLOTS_TEAM + ship;
1734  }
1735  }
1736  }
1737  if(mantis2757switch)
1738  Assert((*team_index != -1) && (*slot_index != -1)); // For tracking down Mantis 2757 - Valathil
1739 }
1740 
1741 // function to return the shipname of the ship in the slot designated by the team and slot
1742 // parameters
1743 void multi_ts_get_shipname( char *ship_name, int team, int slot_index )
1744 {
1745  if ( Netgame.type_flags & NG_TYPE_TEAM ) {
1746  Assert( (team >= 0) && (team < MULTI_TS_MAX_TVT_TEAMS) );
1747  wing_bash_ship_name(ship_name, TVT_wing_names[team], slot_index);
1748  } else {
1749  Assert( team == 0 );
1751  }
1752 }
1753 
1754 // assign the correct flags to the correct slots
1756 {
1757  int idx,s_idx;
1758 
1759  // zero out the flags
1760  for(idx=0;idx<MULTI_TS_MAX_TVT_TEAMS;idx++){
1761  for(s_idx=0;s_idx<MULTI_TS_NUM_SHIP_SLOTS;s_idx++){
1762  Multi_ts_team[idx].multi_ts_flag[s_idx] = MULTI_TS_FLAG_NONE;
1763  }
1764  }
1765 
1766  // in a team vs. team situation
1768  for(idx=0;idx<MULTI_TS_MAX_TVT_TEAMS;idx++){
1769  for(s_idx=0;s_idx<MULTI_TS_NUM_SHIP_SLOTS_TEAM;s_idx++){
1770  // if the there is an objnum here but no ship class, we know its currently empty
1771  if((Multi_ts_team[idx].multi_ts_objnum[s_idx] != -1) && (Wss_slots_teams[idx][s_idx].ship_class == -1)){
1772  Multi_ts_team[idx].multi_ts_flag[s_idx] = MULTI_TS_FLAG_EMPTY;
1773  } else if((Multi_ts_team[idx].multi_ts_objnum[s_idx] != -1) && (Wss_slots_teams[idx][s_idx].ship_class != -1)){
1774  Multi_ts_team[idx].multi_ts_flag[s_idx] = Wss_slots_teams[idx][s_idx].ship_class;
1775  }
1776  }
1777  }
1778  }
1779  // in a non team vs. team situation
1780  else {
1781  for(idx=0;idx<MULTI_TS_NUM_SHIP_SLOTS;idx++){
1782  // if the there is an objnum here but no ship class, we know its currently empty
1783  if((Multi_ts_team[0].multi_ts_objnum[idx] != -1) && (Wss_slots[idx].ship_class == -1)){
1784  Multi_ts_team[0].multi_ts_flag[idx] = MULTI_TS_FLAG_EMPTY;
1785  } else if((Multi_ts_team[0].multi_ts_objnum[idx] != -1) && (Wss_slots[idx].ship_class != -1)){
1786  Multi_ts_team[0].multi_ts_flag[idx] = Wss_slots[idx].ship_class;
1787  }
1788  }
1789  }
1790 }
1791 
1792 // handle an available ship scroll down button press
1794 {
1798  } else {
1800  }
1801 }
1802 
1803 // handle an available ship scroll up button press
1805 {
1806  if(Multi_ts_avail_start > 0){
1809  } else {
1811  }
1812 }
1813 
1814 // handle all mouse events (clicking, dragging, and dropping)
1816 {
1817  int snazzy_region,snazzy_action;
1818  int region_type,region_index,region_empty;
1819  int mouse_x,mouse_y,ship_class;
1820 
1821  // get the mouse coords
1822  mouse_get_pos_unscaled(&mouse_x,&mouse_y);
1823 
1824  // do frame for the snazzy menu
1825  snazzy_region = snazzy_menu_do(Multi_ts_mask_data, Multi_ts_mask_w, Multi_ts_mask_h, Multi_ts_snazzy_regions, Multi_ts_region, &snazzy_action, 0);
1826 
1827  region_type = -1;
1828  region_index = -1;
1829  region_empty = 1;
1830  ship_class = -1;
1831  if(snazzy_region != -1){
1832  region_type = multi_ts_region_type(snazzy_region);
1833  Assert(region_type != -1);
1834 
1835  // determine what type of region the mouse is over and the appropriate index
1836  switch(region_type){
1837  case MULTI_TS_AVAIL_LIST:
1838  region_index = multi_ts_avail_index(snazzy_region);
1839  ship_class = multi_ts_get_avail_ship_class(region_index);
1840 
1841  if(ship_class == -1){
1842  region_empty = 1;
1843  } else {
1844  region_empty = (Ss_pool[ship_class] > 0) ? 0 : 1;
1845  }
1846  break;
1847  case MULTI_TS_SLOT_LIST:
1848  region_index = multi_ts_slot_index(snazzy_region);
1849  if(region_index >= 0 ) {
1850  region_empty = (Multi_ts_team[Net_player->p_info.team].multi_ts_flag[region_index] >= 0) ? 0 : 1;
1851  if(!region_empty){
1852  ship_class = Wss_slots[region_index].ship_class;
1853  }
1854  }
1855  break;
1856  case MULTI_TS_PLAYER_LIST:
1857  region_index = multi_ts_player_index(snazzy_region);
1858  if(region_index >= 0 ) {
1859  region_empty = (Multi_ts_team[Net_player->p_info.team].multi_ts_player[region_index] != NULL) ? 0 : 1;
1860  }
1861  break;
1862  }
1863  }
1864 
1865  // maybe play a "highlight" sound
1866  switch(region_type){
1867  case MULTI_TS_PLAYER_LIST:
1868  if((Multi_ts_hotspot_index != region_index) && (region_index >= 0) && (Multi_ts_team[Net_player->p_info.team].multi_ts_player[region_index] != NULL)){
1870  }
1871  break;
1872  }
1873 
1874  // set the current frame mouse hotspot vars
1875  Multi_ts_hotspot_type = region_type;
1876  Multi_ts_hotspot_index = region_index;
1877 
1878  // if we currently have clicked on something and have just released it
1881  }
1882 
1883  // if we're currently not carrying anything and the user has clicked
1885  // set the "clicked" flag
1887 
1888  // check to see if he clicked on a ship type and highlight if necessary
1889  switch(region_type){
1890  // selected a ship in the wing slots
1891  case MULTI_TS_SLOT_LIST:
1893  Multi_ts_select_index = region_index;
1895  break;
1896 
1897  // selected a ship on the avail list
1898  case MULTI_TS_AVAIL_LIST:
1900  Multi_ts_select_index = region_index;
1902  break;
1903 
1904  // selected something else - unselect
1905  default :
1906  Multi_ts_select_type = -1;
1907  Multi_ts_select_index = -1;
1909  break;
1910  }
1911 
1912  Multi_ts_clicked_x = mouse_x;
1913  Multi_ts_clicked_y = mouse_y;
1914  }
1915 
1916  // if we had something clicked and have started dragging it
1918  // if this player is an observer, he shouldn't be able to do jack
1920  return;
1921  }
1922 
1923  // first we check for illegal conditions (any case where he cannot grab what he is attempting to grab)
1924  switch(region_type){
1925  case MULTI_TS_AVAIL_LIST :
1926  // if players are not yet locked, can't grab ships
1927  if(!Multi_ts_team[Net_player->p_info.team].multi_players_locked){
1928  return;
1929  }
1930 
1931  if(region_empty){
1932  return;
1933  }
1934  break;
1935  case MULTI_TS_SLOT_LIST:
1936  // if players are not yet locked, can't grab ships
1937  if(!Multi_ts_team[Net_player->p_info.team].multi_players_locked){
1938  return;
1939  }
1940 
1941  if(multi_ts_disabled_slot(region_index)){
1943  return;
1944  }
1945  if(region_index >= 0 ) {
1946  if(Multi_ts_team[Net_player->p_info.team].multi_ts_flag[region_index] < 0){
1947  return;
1948  }
1949  }
1950  break;
1951  case MULTI_TS_PLAYER_LIST:
1952  if(!multi_ts_can_grab_player(region_index)){
1953  return;
1954  }
1955  break;
1956  }
1957 
1958 
1961 
1962  // set up the carried icon here
1963  Multi_ts_carried_from_type = region_type;
1964  Multi_ts_carried_from_index = region_index;
1965  Multi_ts_carried_ship_class = ship_class;
1966  }
1967 
1968  // if we were carrying something but have dropped it
1971  Multi_ts_clicked_flag = 0;
1972 
1973  // if we're not allowed to drop onto this slot
1974  if((region_type == MULTI_TS_SLOT_LIST) && multi_ts_disabled_slot(region_index)){
1976  }
1977 
1978  // if we're over some kind of valid region, apply
1980  }
1981 }
1982 
1983 // can the specified player perform the action he is attempting
1984 int multi_ts_can_perform(int from_type,int from_index,int to_type,int to_index,int ship_class,int player_index)
1985 {
1986  net_player *pl;
1987  int op_type;
1988  p_object *pobj;
1989 
1990  // get the appropriate player
1991  if(player_index == -1){
1992  pl = Net_player;
1993  } else {
1994  pl = &Net_players[player_index];
1995  }
1996 
1997  // get the operation type
1998  op_type = multi_ts_get_dnd_type(from_type,from_index,to_type,to_index,player_index);
1999 
2000  // if either of the indices are bogus, then bail
2001  if((from_index == -1) || (to_index == -1)){
2002  return 0;
2003  }
2004 
2005  switch(op_type){
2006  case TS_GRAB_FROM_LIST:
2007  // if there are no more of this ship class, its no go
2008  if(Ss_pool_teams[pl->p_info.team][ship_class] <= 0){
2009  return 0;
2010  }
2011 
2012  // if he's not allowed to touch the wing slot
2013  if(multi_ts_disabled_slot(to_index,player_index)){
2014  return 0;
2015  }
2016 
2017  // if the slot he's trying to drop it on is "permanently" empty
2018  if(Multi_ts_team[pl->p_info.team].multi_ts_flag[to_index] == MULTI_TS_FLAG_NONE){
2019  return 0;
2020  }
2021  break;
2022 
2023  case TS_SWAP_LIST_SLOT:
2024  // if there are no more of this ship class, its no go
2025  if(Ss_pool_teams[pl->p_info.team][ship_class] <= 0){
2026  return 0;
2027  }
2028 
2029  // if he's not allowed to touch the wing slot
2030  if(multi_ts_disabled_slot(to_index,player_index)){
2031  return 0;
2032  }
2033 
2034  // if the slot we're trying to move to is invalid, then do nothing
2035  if(Multi_ts_team[pl->p_info.team].multi_ts_flag[to_index] == MULTI_TS_FLAG_NONE){
2036  return 0;
2037  }
2038  break;
2039 
2040  case TS_SWAP_SLOT_SLOT:
2041  // if he's not allowed to touch one of the slots, its no go
2042  if(multi_ts_disabled_slot(from_index,player_index) || multi_ts_disabled_slot(to_index,player_index)){
2043  return 0;
2044  }
2045 
2046  // if the slot we're taking from is invalid
2047  if(Multi_ts_team[pl->p_info.team].multi_ts_flag[to_index] == MULTI_TS_FLAG_NONE){
2048  return 0;
2049  }
2050  break;
2051 
2052  case TS_DUMP_TO_LIST:
2053  // if he's not allowed to be touching the slot to begin with, it no go
2054  if(multi_ts_disabled_slot(from_index,player_index)){
2055  return 0;
2056  }
2057 
2058  // if the slot we're trying to move to is invalid, then do nothing
2059  if(Multi_ts_team[pl->p_info.team].multi_ts_flag[to_index] == MULTI_TS_FLAG_NONE){
2060  return 0;
2061  }
2062  break;
2063 
2064  case TS_SWAP_PLAYER_PLAYER:
2065  // if his team is already locked, he cannot do this
2066  if(Multi_ts_team[pl->p_info.team].multi_players_locked){
2067  return 0;
2068  }
2069 
2070  // if there isn't a player at one of the positions
2071  if((Multi_ts_team[pl->p_info.team].multi_ts_player[from_index] == NULL) || (Multi_ts_team[pl->p_info.team].multi_ts_player[to_index] == NULL)){
2072  return 0;
2073  }
2074 
2075  // if this is not a player ship type object
2076  if(Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index] != -1){
2078  if((pobj == NULL) || !(pobj->flags & OF_PLAYER_SHIP)){
2079  return 0;
2080  }
2081  }
2082 
2084  // if he's not the team captain, he cannot do this
2085  if(!(pl->flags & NETINFO_FLAG_TEAM_CAPTAIN)){
2086  return 0;
2087  }
2088  } else {
2089  // if he's not the host, he cannot do this
2090  if(!(pl->flags & NETINFO_FLAG_GAME_HOST)){
2091  return 0;
2092  }
2093  }
2094  break;
2095 
2096  case TS_MOVE_PLAYER:
2097  // if his team is already locked, he cannot do this
2098  if(Multi_ts_team[pl->p_info.team].multi_players_locked){
2099  return 0;
2100  }
2101 
2102  // if there isn't a player at the _from_
2103  if(Multi_ts_team[pl->p_info.team].multi_ts_player[from_index] == NULL){
2104  return 0;
2105  }
2106 
2107  // if there is no ship at the _to_ location
2108  if(Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index] < 0){
2109  return 0;
2110  }
2111 
2112  // if this is not a player ship type object
2113  if(Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index] != -1){
2115  if((pobj == NULL) || !(pobj->flags & OF_PLAYER_SHIP)){
2116  return 0;
2117  }
2118  }
2119 
2121  // if he's not the team captain, he cannot do this
2122  if(!(pl->flags & NETINFO_FLAG_TEAM_CAPTAIN)){
2123  return 0;
2124  }
2125  } else {
2126  // if he's not the host, he cannot do this
2127  if(!(pl->flags & NETINFO_FLAG_GAME_HOST)){
2128  return 0;
2129  }
2130  }
2131  break;
2132 
2133  default :
2134  return 0;
2135  break;
2136  }
2137 
2138  return 1;
2139 }
2140 
2141 // determine the kind of drag and drop operation this is
2142 int multi_ts_get_dnd_type(int from_type,int from_index,int to_type,int to_index,int player_index)
2143 {
2144  net_player *pl;
2145 
2146  // get the appropriate player
2147  if(player_index == -1){
2148  pl = Net_player;
2149  } else {
2150  pl = &Net_players[player_index];
2151  }
2152 
2153  switch(from_type){
2154  // came from the ship avail list
2155  case MULTI_TS_AVAIL_LIST :
2156  // do nothing
2157  if(to_type == MULTI_TS_AVAIL_LIST){
2158  return -1;
2159  }
2160 
2161  // if placing it on a slot
2162  if(to_type == MULTI_TS_SLOT_LIST){
2163  if(Wss_slots_teams[pl->p_info.team][to_index].ship_class == -1){
2164  return TS_GRAB_FROM_LIST;
2165  } else {
2166  return TS_SWAP_LIST_SLOT;
2167  }
2168  }
2169  break;
2170 
2171  // came from the ship slots
2172  case MULTI_TS_SLOT_LIST :
2173  if(to_type == MULTI_TS_SLOT_LIST){
2174  return TS_SWAP_SLOT_SLOT;
2175  }
2176  if(to_type == MULTI_TS_AVAIL_LIST){
2177  return TS_DUMP_TO_LIST;
2178  }
2179  break;
2180 
2181  // came from the player lists
2182  case MULTI_TS_PLAYER_LIST :
2183  if(to_type == MULTI_TS_PLAYER_LIST){
2184  if(Multi_ts_team[pl->p_info.team].multi_ts_player[to_index] == NULL){
2185  return TS_MOVE_PLAYER;
2186  } else {
2187  return TS_SWAP_PLAYER_PLAYER;
2188  }
2189  }
2190  break;
2191  }
2192 
2193  return -1;
2194 }
2195 
2196 void multi_ts_apply(int from_type,int from_index,int to_type,int to_index,int ship_class,int player_index)
2197 {
2198  int size,update,sound;
2199  ubyte wss_data[MAX_PACKET_SIZE-20];
2200  net_player *pl;
2201 
2202  // determine what kind of operation this is
2203  int type = multi_ts_get_dnd_type(from_type,from_index,to_type,to_index,player_index);
2204 
2205  // get the proper net player
2206  if(player_index == -1){
2207  pl = Net_player;
2208  } else {
2209  pl = &Net_players[player_index];
2210  }
2211 
2212  // set the proper pool pointers
2214 
2215  sound = -1;
2216  switch(type){
2217  case TS_SWAP_SLOT_SLOT :
2218  nprintf(("Network","Apply swap slot slot %d %d\n",from_index,to_index));
2219  update = ss_swap_slot_slot(from_index,to_index,&sound);
2220  break;
2221  case TS_DUMP_TO_LIST :
2222  nprintf(("Network","Apply dump to list %d %d\n",from_index,to_index));
2223  update = ss_dump_to_list(from_index,ship_class,&sound);
2224  break;
2225  case TS_SWAP_LIST_SLOT :
2226  nprintf(("Network","Apply swap list slot %d %d\n",from_index,to_index));
2227  update = ss_swap_list_slot(ship_class,to_index,&sound);
2228  break;
2229  case TS_GRAB_FROM_LIST :
2230  nprintf(("Network","Apply grab from list %d %d\n",from_index,to_index));
2231  update = ss_grab_from_list(ship_class,to_index,&sound);
2232  break;
2233  case TS_SWAP_PLAYER_PLAYER :
2234  nprintf(("Network","Apply swap player player %d %d\n",from_index,to_index));
2235  update = multi_ts_swap_player_player(from_index,to_index,&sound,player_index);
2236  break;
2237  case TS_MOVE_PLAYER :
2238  nprintf(("Network","Apply move player %d %d\n",from_index,to_index));
2239  update = multi_ts_move_player(from_index,to_index,&sound,player_index);
2240  break;
2241  default :
2242  update = 0;
2243  break;
2244  }
2245 
2246  if(update){
2247  // if we're the host, send an update to all players
2248  if ( MULTIPLAYER_HOST ) {
2249  // send the correct type of update
2250  if(type == TS_SWAP_PLAYER_PLAYER){
2251  } else {
2252  size = store_wss_data(wss_data, MAX_PACKET_SIZE-20, sound, player_index);
2253  send_wss_update_packet(pl->p_info.team,wss_data, size);
2254 
2255  // send a player slot update packet as well, so ship class information, etc is kept correct
2257  }
2258 
2259  // if the player index == -1, it means the action was done locally - so play a sound
2260  if((player_index == -1) && (sound != -1)){
2261  gamesnd_play_iface(sound);
2262  }
2263  }
2264 
2265  // sync the interface screen up ourselves, if necessary
2266  if(Net_player->p_info.team == pl->p_info.team){
2268  }
2269 
2270  // make sure all flags are set properly for all teams
2272  }
2273 
2274  // set the proper pool pointers
2276 }
2277 
2278 // drop a carried icon
2279 void multi_ts_drop(int from_type,int from_index,int to_type,int to_index,int ship_class,int player_index)
2280 {
2281  // if I'm the host, apply immediately
2283  // if this is a legal operation
2284  if(multi_ts_can_perform(from_type,from_index,to_type,to_index,ship_class,player_index)){
2285  multi_ts_apply(from_type,from_index,to_type,to_index,ship_class,player_index);
2286  } else {
2287  nprintf(("Network","Could not apply operation!\n"));
2288  }
2289  }
2290  // otherwise send a request to the host
2291  else {
2292  send_wss_request_packet(Net_player->player_id, from_type, from_index, to_type, to_index, -1, ship_class, WSS_SHIP_SELECT);
2293  }
2294 }
2295 
2296 // swap two player positions
2297 int multi_ts_swap_player_player(int from_index,int to_index,int *sound,int player_index)
2298 {
2299  net_player *pl,*temp;
2300 
2301  // get the proper player pointer
2302  if(player_index == -1){
2303  pl = Net_player;
2304  } else {
2305  pl = &Net_players[player_index];
2306  }
2307 
2308  // swap the players
2309  temp = Multi_ts_team[pl->p_info.team].multi_ts_player[to_index];
2310  Multi_ts_team[pl->p_info.team].multi_ts_player[to_index] = Multi_ts_team[pl->p_info.team].multi_ts_player[from_index];
2311  Multi_ts_team[pl->p_info.team].multi_ts_player[from_index] = temp;
2312 
2313  // update netplayer information if necessary
2314  if(Multi_ts_team[pl->p_info.team].multi_ts_player[from_index] != NULL){
2315  Multi_ts_team[pl->p_info.team].multi_ts_player[from_index]->p_info.ship_index = from_index;
2316  Multi_ts_team[pl->p_info.team].multi_ts_player[from_index]->p_info.ship_class = Wss_slots_teams[pl->p_info.team][from_index].ship_class;
2317 
2318  multi_assign_player_ship(NET_PLAYER_INDEX(Multi_ts_team[pl->p_info.team].multi_ts_player[from_index]),&Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[from_index]],Wss_slots_teams[pl->p_info.team][from_index].ship_class);
2319  }
2320  if(Multi_ts_team[pl->p_info.team].multi_ts_player[to_index] != NULL){
2321  Multi_ts_team[pl->p_info.team].multi_ts_player[to_index]->p_info.ship_index = to_index;
2322  Multi_ts_team[pl->p_info.team].multi_ts_player[to_index]->p_info.ship_class = Wss_slots_teams[pl->p_info.team][to_index].ship_class;
2323 
2324  multi_assign_player_ship(NET_PLAYER_INDEX(Multi_ts_team[pl->p_info.team].multi_ts_player[to_index]),&Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index]],Wss_slots_teams[pl->p_info.team][to_index].ship_class);
2325  }
2326 
2327  // update ship flags
2328  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index]].flags &= ~(OF_COULD_BE_PLAYER);
2329  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index]].flags &= ~(OF_PLAYER_SHIP);
2330  if(Multi_ts_team[pl->p_info.team].multi_ts_player[to_index] != NULL){
2331  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index]].flags |= OF_PLAYER_SHIP;
2332  }
2333  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[from_index]].flags &= ~(OF_COULD_BE_PLAYER);
2334  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[from_index]].flags &= ~(OF_PLAYER_SHIP);
2335  if(Multi_ts_team[pl->p_info.team].multi_ts_player[from_index] != NULL){
2336  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[from_index]].flags |= OF_PLAYER_SHIP;
2337  }
2338 
2339  // recalcalate which slots are locked/unlocked, etc
2341 
2342  // send an update packet to all players
2346  }
2347 
2348  *sound = SND_ICON_DROP;
2349 
2350  return 1;
2351 }
2352 
2353 // move a player
2354 int multi_ts_move_player(int from_index,int to_index,int *sound,int player_index)
2355 {
2356  net_player *pl;
2357 
2358  // get the proper player pointer
2359  if(player_index == -1){
2360  pl = Net_player;
2361  } else {
2362  pl = &Net_players[player_index];
2363  }
2364 
2365  // swap the players
2366  Multi_ts_team[pl->p_info.team].multi_ts_player[to_index] = Multi_ts_team[pl->p_info.team].multi_ts_player[from_index];
2367  Multi_ts_team[pl->p_info.team].multi_ts_player[from_index] = NULL;
2368 
2369  // update netplayer information if necessary
2370  if(Multi_ts_team[pl->p_info.team].multi_ts_player[from_index] != NULL){
2371  Multi_ts_team[pl->p_info.team].multi_ts_player[from_index]->p_info.ship_index = from_index;
2372  Multi_ts_team[pl->p_info.team].multi_ts_player[from_index]->p_info.ship_class = Wss_slots_teams[pl->p_info.team][from_index].ship_class;
2373 
2374  multi_assign_player_ship(NET_PLAYER_INDEX(Multi_ts_team[pl->p_info.team].multi_ts_player[from_index]),&Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[from_index]],Wss_slots_teams[pl->p_info.team][from_index].ship_class);
2375  }
2376  if(Multi_ts_team[pl->p_info.team].multi_ts_player[to_index] != NULL){
2377  Multi_ts_team[pl->p_info.team].multi_ts_player[to_index]->p_info.ship_index = to_index;
2378  Multi_ts_team[pl->p_info.team].multi_ts_player[to_index]->p_info.ship_class = Wss_slots_teams[pl->p_info.team][to_index].ship_class;
2379 
2380  multi_assign_player_ship(NET_PLAYER_INDEX(Multi_ts_team[pl->p_info.team].multi_ts_player[to_index]),&Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index]],Wss_slots_teams[pl->p_info.team][to_index].ship_class);
2381  }
2382 
2383  // update ship flags
2384  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index]].flags &= ~(OF_COULD_BE_PLAYER);
2385  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index]].flags &= ~(OF_PLAYER_SHIP);
2386  if(Multi_ts_team[pl->p_info.team].multi_ts_player[to_index] != NULL){
2387  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[to_index]].flags |= OF_PLAYER_SHIP;
2388  }
2389  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[from_index]].flags &= ~(OF_COULD_BE_PLAYER);
2390  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[from_index]].flags &= ~(OF_PLAYER_SHIP);
2391  if(Multi_ts_team[pl->p_info.team].multi_ts_player[from_index] != NULL){
2392  Objects[Multi_ts_team[pl->p_info.team].multi_ts_objnum[from_index]].flags |= OF_PLAYER_SHIP;
2393  }
2394 
2395  // recalcalate which slots are locked/unlocked, etc
2397 
2398  // send an update packet to all players
2402  }
2403 
2404  *sound = SND_ICON_DROP;
2405 
2406  return 1;
2407 }
2408 
2409 // get the ship class of the current index in the avail list or -1 if none exists
2411 {
2412  int ship_count,class_index;
2413 
2414  ship_count = index + Multi_ts_avail_start;
2415  class_index = 0;
2416  while((ship_count >= 0) && (class_index < static_cast<int>(Ship_info.size()))){
2417  if(Ss_pool[class_index] > 0){
2418  ship_count--;
2419  }
2420 
2421  if(ship_count >= 0){
2422  class_index++;
2423  }
2424  }
2425 
2426  if(ship_count < 0){
2427  return class_index;
2428  }
2429 
2430  return -1;
2431 }
2432 
2433 // blit the currently carried icon (if any)
2435 {
2436  int x,y;
2437  int offset_x,offset_y,callsign_w;
2438  char callsign[CALLSIGN_LEN+2];
2439 
2440  // if we're not carrying anything, then return
2441  if(!Multi_ts_carried_flag){
2442  return;
2443  }
2444 
2445  // get the mouse position
2446  mouse_get_pos_unscaled(&x,&y);
2447 
2448  // if we're carrying an icon of some kind
2450  case MULTI_TS_SLOT_LIST:
2451  offset_x = Multi_ts_slot_icon_coords[Multi_ts_carried_from_index][gr_screen.res][MULTI_TS_X_COORD] - Multi_ts_clicked_x;
2452  offset_y = Multi_ts_slot_icon_coords[Multi_ts_carried_from_index][gr_screen.res][MULTI_TS_Y_COORD] - Multi_ts_clicked_y;
2453 
2454  // blit the icon
2455  ss_blit_ship_icon(x + offset_x,y + offset_y,Multi_ts_carried_ship_class,0);
2456  break;
2457  case MULTI_TS_AVAIL_LIST:
2458  offset_x = Multi_ts_avail_coords[Multi_ts_carried_from_index][gr_screen.res][MULTI_TS_X_COORD] - Multi_ts_clicked_x;
2459  offset_y = Multi_ts_avail_coords[Multi_ts_carried_from_index][gr_screen.res][MULTI_TS_Y_COORD] - Multi_ts_clicked_y;
2460 
2461  // blit the icon
2462  ss_blit_ship_icon(x + offset_x,y + offset_y,Multi_ts_carried_ship_class,0);
2463  break;
2464  case MULTI_TS_PLAYER_LIST:
2465  // get the final length of the string so we can calculate a valid offset
2467  gr_force_fit_string(callsign,CALLSIGN_LEN,Multi_ts_slot_text_coords[Multi_ts_carried_from_index][gr_screen.res][MULTI_TS_W_COORD]);
2468  gr_get_string_size(&callsign_w,NULL,callsign);
2469 
2470  // calculate the offsets
2471  offset_x = (Multi_ts_slot_text_coords[Multi_ts_carried_from_index][gr_screen.res][MULTI_TS_X_COORD] - Multi_ts_clicked_x) + ((Multi_ts_slot_text_coords[Multi_ts_carried_from_index][gr_screen.res][MULTI_TS_W_COORD] - callsign_w)/2);
2472  offset_y = Multi_ts_slot_text_coords[Multi_ts_carried_from_index][gr_screen.res][MULTI_TS_Y_COORD] - Multi_ts_clicked_y;
2473 
2475  gr_string(x + offset_x,y + offset_y,Multi_ts_team[Net_player->p_info.team].multi_ts_player[Multi_ts_carried_from_index]->m_player->callsign,GR_RESIZE_MENU);
2476  break;
2477  default :
2478  break;
2479  }
2480 }
2481 
2482 // if the (console) player is allowed to grab a player slot at this point
2483 int multi_ts_can_grab_player(int slot_index, int player_index)
2484 {
2485  net_player *pl;
2486 
2487  // get a pointe rto the proper net player
2488  if(player_index == -1){
2489  pl = Net_player;
2490  } else {
2491  pl = &Net_players[player_index];
2492  }
2493 
2494  // if the players are locked in any case, he annot grab it
2495  if(Multi_ts_team[pl->p_info.team].multi_players_locked){
2496  return 0;
2497  }
2498 
2500  // if he's not the team captain, he cannot do this
2501  if(!(pl->flags & NETINFO_FLAG_TEAM_CAPTAIN)){
2502  return 0;
2503  }
2504  } else {
2505  // if he's not the host, he cannot do this
2506  if(!(pl->flags & NETINFO_FLAG_GAME_HOST)){
2507  return 0;
2508  }
2509  }
2510 
2511  // if the slot is empty
2512  if(Multi_ts_team[pl->p_info.team].multi_ts_player[slot_index] == NULL){
2513  return 0;
2514  }
2515 
2516  return 1;
2517 }
2518 
2519 // get the team # of the given ship
2520 int multi_ts_get_team(char *ship_name)
2521 {
2522  int idx;//,s_idx;
2523 
2524  // lookup through all team ship names
2526  for(idx=0;idx<MAX_TVT_WINGS;idx++)
2527  {
2528  if (!strnicmp(ship_name, TVT_wing_names[idx], strlen(TVT_wing_names[idx])))
2529  return idx;
2530  }
2531 
2532  // always on team 0 if not found otherwise
2533  return 0;
2534 }
2535 
2536 // return the bitmap index into the ships icon array (in ship select) which should be displayed for the given slot
2537 int multi_ts_avail_bmap_num(int slot_index)
2538 {
2539  // if this slot has been highlighted for informational purposes
2541  return ICON_FRAME_SELECTED;
2542  }
2543 
2544  // if its otherwise being lit by the mouse
2546  return ICON_FRAME_HOT;
2547  }
2548 
2549  return ICON_FRAME_NORMAL;
2550 }
2551 
2552 // return the bitmap index into the ships icon array (in ship select) which should be displayed for the given slot
2553 int multi_ts_slot_bmap_num(int slot_index)
2554 {
2555  // special case - slot is disabled, its my ship and the host hasn't locked the ships yet
2556  if(multi_ts_disabled_high_slot(slot_index)){
2557  return ICON_FRAME_DISABLED_HIGH;
2558  }
2559 
2560  // if this slot is disabled for us, then show it as such
2561  if(multi_ts_disabled_slot(slot_index)){
2562  return ICON_FRAME_DISABLED;
2563  }
2564 
2565  // if this slot has been highlighted for informational purposes
2567  return ICON_FRAME_SELECTED;
2568  }
2569 
2570  // if this is our ship, then highlight it as so
2571  if(Net_player->p_info.ship_index == slot_index){
2572  return ICON_FRAME_PLAYER;
2573  }
2574 
2575  // if its otherwise being lit by the mouse
2577  return ICON_FRAME_HOT;
2578  }
2579 
2580  // normal unhighlighted frame
2581  return ICON_FRAME_NORMAL;
2582 }
2583 
2584 // select the given slot and setup any information, etc
2586 {
2587  int n_lines;
2588  int n_chars[MAX_BRIEF_LINES];
2589  char ship_desc[1000];
2590  const char *p_str[MAX_BRIEF_LINES];
2591  char *token;
2592 
2593 
2594  // blast all current text
2597 
2598  // get the selected ship class
2601  switch(Multi_ts_select_type){
2602  case MULTI_TS_SLOT_LIST:
2604  break;
2605  case MULTI_TS_AVAIL_LIST:
2607  // if he has selected an empty slot, don't do anything
2609  return;
2610  }
2611  break;
2612  default :
2613  // should always have one of the 2 above types selected
2614  Int3();
2615  break;
2616  }
2617 
2618  // split the text info up
2619 
2621 // Assert((Ship_info[Multi_ts_select_ship_class].desc != NULL) && strlen(Ship_info[Multi_ts_select_ship_class].desc));
2622  if (Ship_info[Multi_ts_select_ship_class].desc != NULL)
2623  {
2624 
2625  // strip out newlines
2626  memset(ship_desc,0,1000);
2628  token = strtok(ship_desc,"\n");
2629  if(token != NULL){
2631  while(token != NULL){
2632  token = strtok(NULL,"\n");
2633  if(token != NULL){
2636  }
2637  }
2638  }
2639 
2640  if(Multi_ts_ship_info_text[0] != '\0'){
2641  // split the string into multiple lines
2642  n_lines = split_str(Multi_ts_ship_info_text, Multi_ts_ship_info_coords[gr_screen.res][MULTI_TS_W_COORD], n_chars, p_str, MULTI_TS_SHIP_INFO_MAX_LINES, 0);
2643 
2644  // copy the split up lines into the text lines array
2645  for (int idx = 0;idx<n_lines;idx++ ) {
2647  strncpy(Multi_ts_ship_info_lines[idx], p_str[idx], n_chars[idx]);
2648  Multi_ts_ship_info_lines[idx][n_chars[idx]] = 0;
2650  }
2651 
2652  // get the line count
2654  } else {
2655  // set the line count to
2657  }
2658  }
2659 }
2660 
2661 // handle all details when the commit button is pressed (including possibly reporting errors/popups)
2663 {
2664  // if my team's slots are still not "locked", we cannot commit unless we're the only player in the game
2665  if(!Multi_ts_team[Net_player->p_info.team].multi_players_locked){
2666  if(multi_num_players() != 1){
2667  popup(PF_USE_AFFIRMATIVE_ICON | PF_BODY_BIG,1,POPUP_OK, XSTR("Players have not yet been assigned to their ships",751));
2668  return;
2669  } else {
2670  Multi_ts_team[Net_player->p_info.team].multi_players_locked = 1;
2671  }
2672  }
2673 
2674  // check to see if its not ok for this player to commit
2675  switch(multi_ts_ok_to_commit()){
2676  // yes, it _is_ ok to commit
2677  case 0:
2678  extern void commit_pressed();
2679  commit_pressed();
2680  break;
2681 
2682  // player has not assigned all necessary ships
2683  case 1:
2685  popup(PF_USE_AFFIRMATIVE_ICON | PF_BODY_BIG,1,POPUP_OK, XSTR("You have not yet assigned all necessary ships",752));
2686  break;
2687 
2688  // there are ships without primary weapons
2689  case 2:
2691  popup(PF_USE_AFFIRMATIVE_ICON | PF_BODY_BIG,1,POPUP_OK, XSTR("There are ships without primary weapons!",753));
2692  break;
2693 
2694  // there are ships without secondary weapons
2695  case 3:
2697  popup(PF_USE_AFFIRMATIVE_ICON | PF_BODY_BIG,1,POPUP_OK, XSTR("There are ships without secondary weapons!",754));
2698  break;
2699  }
2700 }
2701 
2702 // is it ok for this player to commit
2704 {
2705  int idx,s_idx;
2706  int primary_ok,secondary_ok;
2707 
2708  // if this player is an observer, he can always commit
2710  return 0;
2711  }
2712 
2713  for(idx=0;idx<MULTI_TS_NUM_SHIP_SLOTS;idx++){
2714  // if this is a player slot this player can modify and it is empty, then he cannot continue
2715  // implies there is never an object in this slot
2716  if((Multi_ts_team[Net_player->p_info.team].multi_ts_objnum[idx] != -1) &&
2717  // implies player can't touch this slot anyway
2718  !multi_ts_disabled_slot(idx) &&
2719  // implies that there should be a player ship here but there isn't
2720  ((Multi_ts_team[Net_player->p_info.team].multi_ts_player[idx] != NULL) && (Multi_ts_team[Net_player->p_info.team].multi_ts_flag[idx] == MULTI_TS_FLAG_EMPTY)) ){
2721  return 1;
2722  }
2723 
2724  // if the ship in this slot has a ship which can be a player but has 0 primary or secondary weapons, then he cannot continue
2725  if( (Multi_ts_team[Net_player->p_info.team].multi_ts_objnum[idx] != -1) &&
2726  ((Objects[Multi_ts_team[Net_player->p_info.team].multi_ts_objnum[idx]].flags & OF_COULD_BE_PLAYER) ||
2727  (Objects[Multi_ts_team[Net_player->p_info.team].multi_ts_objnum[idx]].flags & OF_PLAYER_SHIP)) &&
2728  !multi_ts_disabled_slot(idx)){
2729 
2730  primary_ok = 0;
2731  secondary_ok = 0;
2732  // go through all weapons in the list
2733  for(s_idx=0;s_idx<MAX_SHIP_WEAPONS;s_idx++){
2734  // if this slot has a weapon with a greater than 0 count, check
2735  if((Wss_slots_teams[Net_player->p_info.team][idx].wep[s_idx] >= 0) && (Wss_slots_teams[Net_player->p_info.team][idx].wep_count[s_idx] > 0)){
2736  switch(Weapon_info[Wss_slots_teams[Net_player->p_info.team][idx].wep[s_idx]].subtype){
2737  case WP_LASER:
2738  primary_ok = 1;
2739  break;
2740 
2741  case WP_MISSILE:
2742  secondary_ok = 1;
2743  break;
2744 
2745  default :
2746  Int3();
2747  }
2748  }
2749 
2750  // if we've got both primary and secondary weapons
2751  if(primary_ok && secondary_ok){
2752  break;
2753  }
2754  }
2755 
2756  // if the ship doesn't have primary weapons
2757  if (!primary_ok && !(The_mission.ai_profile->flags & AIPF_MULTI_ALLOW_EMPTY_PRIMARIES)) {
2758  return 2;
2759  }
2760 
2761  // if the ship doesn't have secondary weapons
2762  if (!secondary_ok && !(The_mission.ai_profile->flags & AIPF_MULTI_ALLOW_EMPTY_SECONDARIES)) {
2763  return 3;
2764  }
2765  }
2766  }
2767 
2768  return 0;
2769 }
2770 
2771 // check to see that no illegal ship settings have occurred
2773 {
2774  /*
2775  int idx;
2776  ship *shipp;
2777 
2778  for(idx=0;idx<MULTI_TS_NUM_SHIP_SLOTS;idx++){
2779  if(Multi_ts_team[0].multi_ts_objnum[idx] == -1){
2780  continue;
2781  }
2782 
2783  shipp = &Ships[Objects[Multi_ts_team[0].multi_ts_objnum[idx]].instance];
2784  Assert((shipp->weapons.current_primary_bank != -1) && (shipp->weapons.current_secondary_bank != -1));
2785  }
2786  */
2787 }
2788 
2789 
2790 // ------------------------------------------------------------------------------------------------------
2791 // TEAM SELECT PACKET HANDLERS
2792 //
2793 
2794 // send a player slot position update
2796 {
2797  ubyte data[MAX_PACKET_SIZE],stop,val;
2798  short s_sound;
2799  int idx;
2800  int packet_size = 0;
2801  int i_tmp;
2802 
2803  // build the header and add the data
2805 
2806  // add the opcode
2807  val = (ubyte)code;
2808  ADD_DATA(val);
2809 
2810  // add the team
2811  val = (ubyte)team;
2812  ADD_DATA(val);
2813 
2814  // add the sound to play
2815  s_sound = (short)sound;
2816  ADD_SHORT(s_sound);
2817 
2818  // add data based upon the packet code
2819  switch(code){
2820  case TS_CODE_LOCK_TEAM:
2821  // don't have to do anything
2822  break;
2823  case TS_CODE_PLAYER_UPDATE:
2824  // only the host should ever be doing this
2826 
2827  // add individual slot data
2828  for(idx=0;idx<MAX_WSS_SLOTS;idx++){
2829  if(Multi_ts_team[team].multi_ts_flag[idx] != MULTI_TS_FLAG_NONE){
2830  // add a stop byte
2831  stop = 0x0;
2832  ADD_DATA(stop);
2833 
2834  // add the slot #
2835  val = (ubyte)idx;
2836  ADD_DATA(val);
2837 
2838  // add the ship class
2839  val = (ubyte)Wss_slots_teams[team][idx].ship_class;
2840  ADD_DATA(val);
2841 
2842  // add the objnum we're working with
2843  i_tmp = Multi_ts_team[team].multi_ts_objnum[idx];
2844  ADD_INT(i_tmp);
2845 
2846  // add a byte indicating if a player is here or not
2847  if(Multi_ts_team[team].multi_ts_player[idx] == NULL){
2848  val = 0;
2849  } else {
2850  val = 1;
2851  }
2852  ADD_DATA(val);
2853 
2854  // if there's a player, add his address
2855  if(val){
2856  ADD_SHORT(Multi_ts_team[team].multi_ts_player[idx]->player_id);
2857 
2858  // should also update his p_info settings locally
2860  Multi_ts_team[team].multi_ts_player[idx]->p_info.ship_index = idx;
2861  }
2862 
2863  // add a byte indicating what object flag should be set (0 == ~(OF_COULD_BE_PLAYER | OF_PLAYER_SHIP), 1 == player ship, 2 == could be player ship)
2864  if(Objects[Multi_ts_team[team].multi_ts_objnum[idx]].flags & OF_COULD_BE_PLAYER){
2865  val = 2;
2866  } else if(Objects[Multi_ts_team[team].multi_ts_objnum[idx]].flags & OF_PLAYER_SHIP){
2867  val = 1;
2868  } else {
2869  val = 0;
2870  }
2871  ADD_DATA(val);
2872  }
2873  }
2874  // add a final stop byte
2875  val = 0xff;
2876  ADD_DATA(val);
2877  break;
2878  default :
2879  Int3();
2880  break;
2881  }
2882 
2883  // send the packet to the standalone
2885  multi_io_send_to_all_reliable(data, packet_size);
2886  } else {
2887  multi_io_send_reliable(Net_player, data, packet_size);
2888  }
2889 }
2890 
2891 // process a player slot position update
2893 {
2894  int offset = HEADER_LENGTH;
2895  int my_index;
2896  int player_index,idx,team,code,objnum;
2897  short sound;
2898  short player_id;
2899  ubyte stop,val,slot_num,ship_class;
2900 
2901  my_index = Net_player->p_info.ship_index;
2902 
2903  // if we're the standalone, then we should be routing this data to all the other clients
2904  player_index = -1;
2906  // fill in the address information of where this came from
2907  player_index = find_player_id(hinfo->id);
2908  Assert(player_index != -1);
2909  }
2910 
2911  // get the opcode
2912  GET_DATA(val);
2913  code = (int)val;
2914 
2915  // get the team
2916  GET_DATA(val);
2917  team = (int)val;
2918 
2919  // get the sound to play
2920  GET_SHORT(sound);
2921 
2922  // process the different opcodes
2923  switch(code){
2924  case TS_CODE_LOCK_TEAM:
2925  // lock the team
2926  Multi_ts_team[team].multi_players_locked = 1;
2927 
2928  // if this was my team, sync stuff up
2929  if((team == Net_player->p_info.team) && !(Game_mode & GM_STANDALONE_SERVER)){
2933  }
2934 
2935  // if this is the standalone server, we need to re-route the packet here and there
2937  // in team vs team mode, only a team captain should ever be sending this
2940  }
2941  // in any other mode, it better be coming from the game host
2942  else {
2944  }
2945 
2946  // re-route to all other players
2947  for(idx=0;idx<MAX_PLAYERS;idx++){
2948  if(MULTI_CONNECTED(Net_players[idx]) && (&Net_players[idx] != Net_player) && (&Net_players[idx] != &Net_players[player_index]) ){
2949  multi_io_send_reliable(&Net_players[idx], data, offset);
2950  }
2951  }
2952  }
2953  break;
2954  case TS_CODE_PLAYER_UPDATE:
2955  // get the first stop byte
2956  GET_DATA(stop);
2957  while(stop != 0xff){
2958  // get the slot #
2959  GET_DATA(slot_num);
2960 
2961  // get the ship class
2962  GET_DATA(ship_class);
2963 
2964  // get the objnum
2965  GET_INT(objnum);
2966 
2967  // flag indicating if a player is in this slot
2968  GET_DATA(val);
2969  if(val){
2970  // look the player up
2971  GET_SHORT(player_id);
2972  player_index = find_player_id(player_id);
2973 
2974  // if we couldn't find him
2975  if(player_index == -1){
2976  nprintf(("Network","Couldn't find player for pslot update!\n"));
2977  Multi_ts_team[team].multi_ts_player[slot_num] = NULL;
2978  }
2979  // if we found him, assign him to this ship
2980  else {
2981  Net_players[player_index].p_info.ship_class = (int)ship_class;
2982  Net_players[player_index].p_info.ship_index = (int)slot_num;
2983  multi_assign_player_ship(player_index,&Objects[objnum],(int)ship_class);
2984 
2985  // ui stuff
2986  Multi_ts_team[team].multi_ts_player[slot_num] = &Net_players[player_index];
2987 
2988  // if this was me and my ship index changed, update the weapon select screen
2989  if(my_index != Net_player->p_info.ship_index){
2991 
2992  my_index = Net_player->p_info.ship_index;
2993  }
2994  }
2995  } else {
2996  Multi_ts_team[team].multi_ts_player[slot_num] = NULL;
2997  }
2998 
2999  // get the ship flag byte
3000  GET_DATA(val);
3002  switch(val){
3003  case 1 :
3004  Objects[objnum].flags |= OF_PLAYER_SHIP;
3005  break;
3006  case 2 :
3007  obj_set_flags( &Objects[objnum], Objects[objnum].flags | OF_COULD_BE_PLAYER );
3008  break;
3009  }
3010 
3011  // get the next stop byte
3012  GET_DATA(stop);
3013  }
3014  // if we have a sound we're supposed to play
3015  if((sound != -1) && !(Game_mode & GM_STANDALONE_SERVER) && (gameseq_get_state() == GS_STATE_TEAM_SELECT)){
3016  gamesnd_play_iface(sound);
3017  }
3018 
3019  // if i'm the standalone server, I should rebroadcast this packet
3020  if(Game_mode & GM_STANDALONE_SERVER){
3021  for(idx=0;idx<MAX_PLAYERS;idx++){
3022  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_HOST(Net_players[idx]) && (Net_player != &Net_players[idx])){
3023  multi_io_send_reliable(&Net_players[idx], data, offset);
3024  }
3025  }
3026  }
3027  break;
3028  }
3029  PACKET_SET_SIZE();
3030 
3031  // recalculate stuff
3034  }
3035 }
void ship_wing_cleanup(int shipnum, wing *wingp)
Definition: ship.cpp:7640
int multi_ts_can_perform(int from_type, int from_index, int to_type, int to_index, int ship_class, int player_index=-1)
Definition: sound.cpp:39
#define MULTI_TS_SHIP_INFO_MAX_LINE_LEN
void set_highlight_action(void(*_user_function)(void))
Definition: button.cpp:375
int multi_ts_avail_bmap_num(int slot_index)
void multi_ts_lock_pressed()
char Starting_wing_names[MAX_STARTING_WINGS][NAME_LENGTH]
Definition: ship.cpp:139
wing Wings[MAX_WINGS]
Definition: ship.cpp:128
void multi_ts_avail_scroll_down()
void wing_bash_ship_name(char *ship_name, const char *wing_name, int index)
Definition: ship.cpp:12686
#define MY_NET_PLAYER_NUM
Definition: multi.h:127
int Multi_ts_status_bar_mode
void obj_set_flags(object *obj, uint new_flags)
Definition: object.cpp:1000
int i
Definition: multi_pxo.cpp:466
int chatbox_create(int mode_flags)
Definition: chatbox.cpp:495
#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 Multi_ts_clicked_y
#define MULTI_TS_BRIEFING
UI_WINDOW Multi_ts_window
void multi_ts_check_errors()
int Multi_ts_carried_flag
int ts_index
Definition: ship.h:704
int ship_class
Definition: multi.h:451
#define TSWING_1_NAME_2
int objnum
Definition: ship.h:537
int multi_ts_slot_index(int region)
net_player * multi_ts_player[MULTI_TS_NUM_SHIP_SLOTS]
ui_button_info Multi_ts_buttons[GR_NUM_RESOLUTIONS][MULTI_TS_NUM_BUTTONS]
int Game_mode
Definition: systemvars.cpp:24
void gr_flip()
Definition: 2d.cpp:2113
#define TS_SWAP_PLAYER_PLAYER
int x
Definition: ui.h:658
int Multi_ts_bitmap
#define TS_MOVE_PLAYER
#define ON_SHIP_SELECT
Definition: missionbrief.h:19
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
#define TSWING_LIST_3
#define GR_RESIZE_MENU
Definition: 2d.h:684
net_player * Net_player
Definition: multi.cpp:94
#define MOUSE_LEFT_BUTTON
Definition: mouse.h:43
void multi_ts_blit_ship_info()
#define MULTI_TS_SHIP_SELECT
#define TSWING_2_NAME_1
bool multi_ts_validate_ship(char *shipname, char *wingname)
#define TSWING_1_NAME_3
int y
Definition: ui.h:658
#define PACKET_SET_SIZE()
Definition: multimsgs.h:57
int Multi_ts_num_deleted
GLuint index
Definition: Glext.h:5608
void multi_ts_create_wings()
player * m_player
Definition: multi.h:459
int ss_grab_from_list(int from_list, int to_slot, int *sound)
#define TSWING_2_SHIP_3
#define MAX_WINGS
Definition: globals.h:50
#define MAX_BRIEF_LINES
#define TS_CODE_LOCK_TEAM
drop a ship icon on a wing slot
Definition: gamesnd.h:289
void multi_reset_timestamps()
Definition: multi.cpp:1741
int Multi_ts_select_index
int snazzy_menu_do(ubyte *data, int mask_w, int mask_h, int num_regions, MENU_REGION *regions, int *action, int poll_key, int *key)
Definition: snazzyui.cpp:59
void ss_blit_ship_icon(int x, int y, int ship_class, int bmap_num)
#define TSWING_2_NAME_3
void ship_add_exited_ship(ship *sp, int reason)
Definition: ship.cpp:5298
char Player_start_shipname[NAME_LENGTH]
#define ADD_DATA(d)
Definition: multimsgs.h:37
#define MULTI_STANDALONE(np)
Definition: multi.h:139
int gameseq_get_state(void)
Definition: fredstubs.cpp:60
Assert(pm!=NULL)
void multi_ts_get_team_and_slot(char *ship_name, int *team_index, int *slot_index, bool mantis2757switch)
virtual void draw()
Definition: button.cpp:120
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
void multi_ts_get_shipname(char *ship_name, int team, int slot_index)
#define NETINFO_FLAG_OBSERVER
Definition: multi.h:605
void multi_io_send_to_all_reliable(ubyte *data, int length, net_player *ignore)
Definition: multimsgs.cpp:496
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
general failure sound for any event
Definition: gamesnd.h:297
void multi_ts_init_objnums()
int res
Definition: 2d.h:370
int multi_ts_avail_index(int region)
int max_h_unscaled
Definition: 2d.h:361
void multi_ts_blit_wing_callsigns()
struct vec3d::@225::@227 xyz
CButton * team
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
int multi_ts_can_grab_player(int slot_index, int player_index=-1)
int Multi_ts_mask
void multi_ts_init_graphics()
void multi_ts_init_flags()
#define MULTI_HOST(np)
Definition: multi.h:137
#define SEF_PLAYER_DELETED
Definition: ship.h:849
int multi_ts_slot_bmap_num(int slot_index)
object obj_used_list
Definition: object.cpp:53
int Ss_pool_teams[MAX_TVT_TEAMS][MAX_SHIP_CLASSES]
#define GR_MAYBE_CLEAR_RES(bmap)
Definition: 2d.h:639
#define MAX_WSS_SLOTS
void multi_common_set_palette()
Definition: multiui.cpp:423
int multi_ts_objnum[MULTI_TS_NUM_SHIP_SLOTS]
void wl_reset_selected_slot()
int multi_ts_region_type(int region)
void multi_ts_blit_carried_icon()
int Multi_ts_mask_h
char * Multi_ts_bitmap_fname[GR_NUM_RESOLUTIONS]
void commit_pressed()
int multi_ts_flag[MULTI_TS_NUM_SHIP_SLOTS]
#define TSWING_0_SHIP_1
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
color Color_text_active_hi
Definition: alphacolors.cpp:27
int Multi_ts_select_type
#define MAX_SHIPS_PER_WING
Definition: globals.h:52
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_ts_ship_info_line_count
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
GLsizeiptr size
Definition: Glext.h:5496
int max_w_unscaled
Definition: 2d.h:361
int Multi_ts_select_ship_class
int subtype
Definition: weapon.h:326
#define Int3()
Definition: pstypes.h:292
#define TSWING_1_SHIP_1
void multi_ts_common_init()
int packet_size
Definition: multi_sexp.cpp:41
void multi_ts_assign_players_all()
#define MAX_TVT_WINGS
Definition: globals.h:59
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 MULTI_TS_AVAIL_LIST
#define MULTI_TS_AVAIL_MAX_DISPLAY
void snazzy_menu_add_region(MENU_REGION *region, const char *text, int mask, int key, int click_sound)
Definition: snazzyui.cpp:163
char callsign[CALLSIGN_LEN+1]
Definition: player.h:91
int multi_ts_is_locked()
GLenum type
Definition: Gl.h:1492
void multi_ts_button_pressed(int n)
int mouse_get_pos_unscaled(int *xpos, int *ypos)
Definition: mouse.cpp:580
char name_lookup[MAX_PXO_TEXT_LEN]
Definition: multi_pxo.cpp:4048
int wep_count[MAX_SHIP_WEAPONS]
#define TS_GRAB_FROM_LIST
struct ts_team_data ts_team_data
#define ON_BRIEFING_SELECT
Definition: missionbrief.h:18
#define ADD_INT(d)
Definition: multimsgs.h:40
HWND DWORD code
Definition: vddraw.h:425
#define MULTI_TS_COMMIT
#define TSWING_LIST_0
int Multi_ts_clicked_x
int Multi_ts_avail_start
void draw_forced(int frame_num)
Definition: button.cpp:104
int mouse_down(int btn)
Definition: mouse.cpp:315
int multi_ts_ok_to_commit()
int Multi_ts_snazzy_regions
void multi_ts_apply(int from_type, int from_index, int to_type, int to_index, int ship_class, int player_index)
void destroy()
Definition: window.cpp:189
#define MULTI_TS_SHIP_INFO_MAX_TEXT
#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
void set_mask_bmap(char *fname)
Definition: window.cpp:75
int instance
Definition: object.h:150
void multi_ts_avail_scroll_up()
int multi_num_players()
Definition: multiutil.cpp:1799
int set_bmaps(char *ani_filename, int nframes=3, int start_frame=1)
Definition: gadget.cpp:71
void multi_ts_set_status_bar_mode(int m)
GLintptr offset
Definition: Glext.h:5497
char ship_select_background[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN]
#define NET_PLAYER_INDEX(np)
Definition: multi.h:125
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 chatbox_render()
Definition: chatbox.cpp:683
net_player_info p_info
Definition: multi.h:473
#define TS_CODE_PLAYER_UPDATE
int type_flags
Definition: multi.h:493
#define MAX_SHIP_WEAPONS
Definition: globals.h:64
#define NETINFO_FLAG_AM_MASTER
Definition: multi.h:599
color Color_bright
Definition: alphacolors.cpp:28
int Multi_ts_locked_bitmaps[MULTI_TS_NUM_LOCKED_BITMAPS]
void process_pslot_update_packet(ubyte *data, header *hinfo)
char * manufacturer_str
Definition: ship.h:1172
int state
Definition: multi.h:464
#define nprintf(args)
Definition: pstypes.h:239
multi_server_options options
Definition: multi.h:514
#define GM_MULTIPLAYER
Definition: systemvars.h:18
void multi_ts_check_buttons()
void snazzy_menu_close()
Definition: snazzyui.cpp:276
char Multi_ts_ship_info_lines[MULTI_TS_SHIP_INFO_MAX_LINES][MULTI_TS_SHIP_INFO_MAX_LINE_LEN]
#define BUILD_HEADER(t)
Definition: multimsgs.h:36
char Multi_ts_ship_info_text[MULTI_TS_SHIP_INFO_MAX_TEXT]
#define MULTI_TS_SLOT_LIST
#define MULTI_TS_NUM_LOCKED_BITMAPS
int multi_ts_disabled_slot(int slot_num, int player_index)
ai_profile_t * ai_profile
Definition: missionparse.h:168
ts_team_data Multi_ts_team[MULTI_TS_MAX_TVT_TEAMS]
#define strnicmp(s1, s2, n)
Definition: config.h:272
netgame_info Netgame
Definition: multi.cpp:97
int hotspot
Definition: ui.h:659
#define TSWING_2_SHIP_2
#define MAX_STARTING_WINGS
Definition: globals.h:54
int pressed()
Definition: button.cpp:325
int multi_ts_get_dnd_type(int from_type, int from_index, int to_type, int to_index, int player_index=-1)
#define MULTIPLAYER_HOST
Definition: multi.h:131
int Commit_pressed
#define WP_LASER
Definition: weapon.h:27
#define ICON_FRAME_DISABLED_HIGH
void multi_ts_commit_pressed()
int Multi_ts_avail_count
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define NG_TYPE_TEAM
Definition: multi.h:650
net_player * host
Definition: multi.h:504
int wl_update_ship_weapons(int objnum, wss_unit *slot)
#define KEY_ENTER
Definition: key.h:125
#define AIPF_MULTI_ALLOW_EMPTY_SECONDARIES
Definition: ai_profiles.h:46
char * ship_length
Definition: ship.h:1177
#define MULTI_OBSERVER(np)
Definition: multi.h:140
int Multi_ts_mask_w
#define MSO_FLAG_SS_LEADERS
char * Multi_ts_bitmap_mask_fname[GR_NUM_RESOLUTIONS]
char * type_str
Definition: ship.h:1169
#define TSWING_0_NAME_2
#define NETINFO_FLAG_TEAM_CAPTAIN
Definition: multi.h:612
int split_str(const char *src, int max_pixel_w, int *n_chars, const char **p_str, int max_lines, char ignore_char)
Definition: parselo.cpp:3412
#define MAX_PLAYERS
Definition: pstypes.h:32
short player_id
Definition: multi.h:460
void ss_make_slot_full(int slot_index)
#define MULTI_TS_LOCK
void send_wss_update_packet(int team_num, ubyte *wss_data, int size)
Definition: multimsgs.cpp:5437
int Multi_ts_hotspot_index
int multi_ts_swap_player_player(int from_index, int to_index, int *sound, int player_index=-1)
#define OF_COULD_BE_PLAYER
Definition: object.h:112
#define ADD_SHORT(d)
Definition: multimsgs.h:38
void common_set_team_pointers(int team)
#define NETINFO_FLAG_GAME_HOST
Definition: multi.h:603
UI_BUTTON button
Definition: ui.h:660
#define ICON_FRAME_DISABLED
Definition: ship.h:534
void snazzy_menu_init()
Definition: snazzyui.cpp:34
void multi_ts_blit_avail_ships()
void multi_ts_close()
int idx
Definition: multiui.cpp:761
void multi_ts_init_snazzy()
ubyte * Multi_ts_mask_data
#define TSWING_1_SHIP_3
char name[NAME_LENGTH]
Definition: ship.h:1163
#define TSWING_LIST_1
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
int Next_screen
GLclampd n
Definition: Glext.h:7286
unsigned char ubyte
Definition: pstypes.h:62
#define MULTI_TS_NUM_SHIP_SLOTS_TEAM
int yt
Definition: ui.h:658
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
#define OBJ_INDEX(objp)
Definition: object.h:235
user_click (mouse selects a control)
Definition: gamesnd.h:305
#define NOX(s)
Definition: pstypes.h:473
void multi_ts_init_players()
int ss_swap_slot_slot(int from_slot, int to_slot, int *sound)
char * armor_str
Definition: ship.h:1171
bool end_string_at_first_hash_symbol(char *src)
Definition: parselo.cpp:3833
#define TSWING_0_NAME_1
#define MULTI_TS_WEAPON_SELECT
void multi_ts_drop(int from_type, int from_index, int to_type, int to_index, int ship_class, int player_index)
#define OBJ_SHIP
Definition: object.h:32
#define TSWING_1_SHIP_2
#define GM_STANDALONE_SERVER
Definition: systemvars.h:27
int Multi_ts_inited
#define MULTI_END_NOTIFY_NONE
Definition: multi_endgame.h:32
GLbitfield flags
Definition: Glext.h:6722
int ss_swap_list_slot(int from_list, int to_slot, int *sound)
#define TSWING_2_SHIP_0
#define MULTI_TS_MAX_TVT_TEAMS
#define PROMPT_NONE
Definition: multi_endgame.h:26
wss_unit * Wss_slots
#define TS_SWAP_LIST_SLOT
GLuint GLfloat * val
Definition: Glext.h:6741
int Multi_ts_deleted_objnums[MULTI_TS_MAX_TVT_TEAMS *MULTI_TS_NUM_SHIP_SLOTS]
#define ICON_FRAME_SELECTED
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
int Multi_ts_carried_ship_class
#define MULTI_PERM_OBSERVER(np)
Definition: multi.h:142
briefing * Briefing
int multi_ts_get_avail_ship_class(int index)
int Multi_ts_carried_from_index
MENU_REGION Multi_ts_region[MULTI_TS_NUM_SNAZZY_REGIONS]
char alt_name[NAME_LENGTH]
Definition: ship.h:1164
#define TSWING_2_NAME_2
void obj_delete(int objnum)
Definition: object.cpp:522
#define MULTI_TS_SHIPS_DOWN
#define CALLSIGN_LEN
Definition: globals.h:31
void link_hotspot(int num)
Definition: gadget.cpp:50
int xt
Definition: ui.h:658
ubyte * get_mask_data(int *w_md, int *h_md)
Definition: ui.h:643
#define strcat_s(...)
Definition: safe_strings.h:68
struct sound sound
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
int wep[MAX_SHIP_WEAPONS]
#define TS_SWAP_SLOT_SLOT
#define ON_WEAPON_SELECT
Definition: missionbrief.h:20
#define WP_MISSILE
Definition: weapon.h:28
#define UI_XSTR_COLOR_PINK
Definition: ui.h:161
#define MULTI_TS_SHIP_INFO_MAX_LINES
#define MULTI_TS_SHIPS_UP
#define MULTI_CONNECTED(np)
Definition: multi.h:136
void send_pslot_update_packet(int team, int code, int sound)
void create(int _x, int _y, int _w, int _h, int _flags, int _f_id=-1)
Definition: window.cpp:140
#define TSWING_1_NAME_1
#define ICON_FRAME_HOT
int gr_force_fit_string(char *str, int max_str, int max_width)
Definition: font.cpp:48
#define MULTI_TS_NUM_SHIP_SLOTS
Definition: ui.h:584
#define TS_DUMP_TO_LIST
#define TSWING_1_NAME_0
Definition: multi.h:385
screen gr_screen
Definition: 2d.cpp:46
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
#define MULTI_END_ERROR_SHIP_ASSIGN
Definition: multi_endgame.h:50
int gr_get_font_height()
Definition: font.cpp:187
int store_wss_data(ubyte *block, int max_size, int sound, int player_index)
int ship_info_index
Definition: ship.h:539
int HEADER_LENGTH
Definition: multi.cpp:106
#define ICON_FRAME_PLAYER
char * missile_banks
Definition: ship.h:1179
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
void common_play_highlight_sound()
Definition: gamesnd.cpp:1151
#define TSWING_0_SHIP_3
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
char TVT_wing_names[MAX_TVT_WINGS][NAME_LENGTH]
Definition: ship.cpp:141
void multi_common_voice_display_status()
Definition: multiui.cpp:369
int * Ss_pool
void draw_tooltip()
Definition: window.cpp:304
short id
Definition: multi.h:390
int ss_dump_to_list(int from_slot, int to_list, int *sound)
int multi_ts_player_index(int region)
int chatbox_process(int key_in)
Definition: chatbox.cpp:575
char * maneuverability_str
Definition: ship.h:1170
#define PROMPT_ALL
Definition: multi_endgame.h:29
#define TSWING_2_SHIP_1
const GLfloat * m
Definition: Glext.h:10319
void multi_ts_init()
void multi_ts_maybe_host_only_popup()
#define NETPLAYER_STATE_SHIP_SELECT
Definition: multi.h:681
#define KEY_CTRLED
Definition: key.h:64
color Color_normal
Definition: alphacolors.cpp:28
wss_unit Wss_slots_teams[MAX_TVT_TEAMS][MAX_WSS_SLOTS]
void drop_leading_white_space(char *str)
Definition: parselo.cpp:115
#define KEY_TAB
Definition: key.h:127
void change_ship_type(int n, int ship_type, int by_sexp)
Definition: ship.cpp:9983
char * filename
Definition: ui.h:657
#define MULTI_TS_FLAG_EMPTY
void multi_ts_blit_status_bar()
GLint GLsizei count
Definition: Gl.h:1491
int Multi_ts_clicked_flag
void gr_bitmap(int _x, int _y, int resize_mode)
Definition: 2d.cpp:1303
void multi_ts_handle_player_drop()
void ss_make_slot_empty(int slot_index)
#define TSWING_2_NAME_0
#define UI_XSTR_COLOR_GREEN
Definition: ui.h:160
#define TSWING_0_NAME_3
object * Player_obj
Definition: object.cpp:56
void multi_ts_select_ship()
int ship_index
Definition: multi.h:450
#define GET_SHORT(d)
Definition: multimsgs.h:48
void multi_ts_handle_mouse()
int temp
Definition: lua.cpp:4996
int mission_ui_background_load(const char *custom_background, const char *single_background, const char *multi_background)
void multi_ts_blit_wings()
#define MULTI_TS_NUM_BUTTONS
char * Multi_ts_bmap_names[GR_NUM_RESOLUTIONS][3]
#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
#define AIPF_MULTI_ALLOW_EMPTY_PRIMARIES
Definition: ai_profiles.h:45
int ship_name_lookup(const char *name, int inc_players)
Definition: ship.cpp:12900
#define TSWING_0_SHIP_2
uint flags
Definition: object.h:151
color Color_bright_blue
Definition: alphacolors.cpp:31
#define TSWING_1_SHIP_0
#define SLOT_UPDATE
Definition: multi.h:188
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
mission The_mission
int multi_ts_disabled_high_slot(int slot_index, int player_index)
void disable()
Definition: gadget.cpp:432
void draw()
Definition: window.cpp:220
struct ui_button_info ui_button_info
int Multi_ts_carried_from_type
void multi_ts_sync_interface()
void send_wss_request_packet(short player_id, int from_slot, int from_index, int to_slot, int to_index, int wl_ship_slot, int ship_class, int mode, net_player *p)
Definition: multimsgs.cpp:5360
char type
Definition: object.h:146
int Current_screen
vec3d max_vel
Definition: ship.h:1196
int multi_ts_get_team(char *ship_name)
#define MULTI_TS_NUM_SNAZZY_REGIONS
void ss_recalc_multiplayer_slots()
int process(int key_in=-1, int process_mouse=1)
Definition: window.cpp:401
#define MULTI_TS_X_COORD
#define WSS_SHIP_SELECT
Definition: multi.h:322
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
void gameseq_post_event(int event)
void multi_ts_do()
#define stricmp(s1, s2)
Definition: config.h:271
#define MULTI_TS_W_COORD
drop a ship icon back to the list
Definition: gamesnd.h:290
int wing_lookup(const char *name)
Definition: ship.cpp:12736
#define MULTI_TS_FLAG_NONE
char ship_name[NAME_LENGTH]
Definition: ship.h:604
int multi_ts_move_player(int from_index, int to_index, int *sound, int player_index=-1)
#define ICON_FRAME_NORMAL
#define TSWING_LIST_2
char * gun_mounts
Definition: ship.h:1178
GLint y
Definition: Gl.h:1505
#define TSWING_0_NAME_0
#define MULTI_TS_Y_COORD
#define TSWING_0_SHIP_0
#define MULTI_TS_PLAYER_LIST
#define strcpy_s(...)
Definition: safe_strings.h:67
int Multi_ts_hotspot_type