FS2_Open
Open source remastering of the Freespace 2 engine
hudsquadmsg.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 
14 #include "ai/aigoals.h"
15 #include "gamesnd/gamesnd.h"
16 #include "globalincs/linklist.h"
17 #include "hud/hudmessage.h"
18 #include "hud/hudsquadmsg.h"
19 #include "hud/hudtargetbox.h"
20 #include "iff_defs/iff_defs.h"
21 #include "io/key.h"
22 #include "io/timer.h"
23 #include "mission/missionlog.h"
24 #include "mission/missionmessage.h"
25 #include "network/multi_pmsg.h"
26 #include "network/multimsgs.h"
27 #include "network/multiutil.h"
28 #include "parse/parselo.h"
29 #include "parse/sexp.h"
30 #include "playerman/player.h"
31 #include "ship/ship.h"
32 #include "ship/subsysdamage.h"
33 #include "weapon/emp.h"
34 #include "weapon/weapon.h"
35 
36 
37 // defines for different modes in the squad messaging system
38 
39 #define DEFAULT_MSG_TIMEOUT (8 * 1000) // number of seconds * 1000 to get milliseconds
40 #define MSG_KEY_EAT_TIME (300)
41 
42 int Squad_msg_mode; // current mode that the messaging system is in
43 LOCAL int Msg_key_used; // local variable which tells if the key being processed
44  // with the messaging system was actually used
45 LOCAL int Msg_key; // global which indicates which key was currently pressed
47 int Msg_instance; // variable which holds ship/wing instance to send the message to
48 int Msg_shortcut_command; // holds command when using a shortcut key
49 LOCAL int Msg_target_objnum; // id of the current target of the player
50 LOCAL ship_subsys *Msg_targeted_subsys;// pointer to current subsystem which is targeted
51 LOCAL int Msg_enemies; // tells us whether or not to message enemy ships or friendlies
52 
53 LOCAL int Msg_eat_key_timestamp; // used to temporarily "eat" keys
54 
55 // defined to position the messaging box
57  10,
58  10
59 };
61  17,
62  17
63 };
64 
65 // top of the message box gauge
67  { // GR_640
68  445, 5
69  },
70  { // GR_1024
71  827, 5
72  }
73 };
74 
76  { // GR_640
77  445, 17
78  },
79  { // GR_1024
80  827, 17
81  }
82 };
83 
84 // squadmsg menu pgup and pgdn
86  { // GR_640
87  590, 9
88  },
89  { // GR_1024
90  937, 9
91  }
92 };
94  { // GR_640
95  590, 120
96  },
97  { // GR_1024
98  937, 120
99  }
100 };
101 
102 // -----------
103 // following defines/vars are used to build menus that are used in messaging mode
104 
105 typedef struct mmode_item {
106  int instance; // instance in Ships/Wings array of this menu item
107  int active; // active items are in bold text -- inactive items greyed out
108  char text[NAME_LENGTH]; // text to display on the menu
109 } mmode_item;
110 
111 #define MAX_MENU_ITEMS 50 // max number of items in the menu
112 #define MAX_MENU_DISPLAY 10 // max number that can be displayed
113 
114 char Squad_msg_title[256] = "";
116 int Num_menu_items = -1; // number of items for a message menu
117 int First_menu_item= -1; // index of first item in the menu
118 
119 // -----------
120 // following set of vars/defines are used to store/restore key bindings for keys that
121 // are used in messaging mode
122 
123 // array to temporarily store key bindings that will be in use for the messaging
124 // system
125 typedef struct key_store {
126  int option_num; // which element in the Control_config array is this
127  int id; // which id (1 or 2) is this key.
128  int key_value; // which key value to put there.
129 } key_store;
130 
131 #define MAX_KEYS_NO_SCROLL 10
132 #define MAX_KEYS_USED 12 // maximum number of keys used for the messaging system
133 
134 key_store key_save[MAX_KEYS_USED]; // array to save the key information during messaging mode
135 int num_keys_saved = 0; // number of keys that are saved.
136 
137 // next array is the array of MAX_KEYS_USED size which are the keys to use for messaging mode
138 
141 
142 #define ID1 1
143 #define ID2 2
144 
145 // following are defines and character strings that are used as part of messaging mode
146 
147 #define NUM_COMM_ORDER_TYPES 6
148 
149 #define TYPE_SHIP_ITEM 0
150 #define TYPE_WING_ITEM 1
151 #define TYPE_ALL_FIGHTERS_ITEM 2
152 #define TYPE_REINFORCEMENT_ITEM 3
153 #define TYPE_REPAIR_REARM_ITEM 4
154 #define TYPE_REPAIR_REARM_ABORT_ITEM 5
155 
156 
159 
160 
161 // Goober5000
162 // this is stupid, but localization won't work otherwise
163 // Karajorma
164 // moving the defines to a non-temporary array is no less stupid. But at least now the SEXP system can get at them.
166  {
167  // common stuff
168  { "Destroy my target", 299, ATTACK_TARGET_ITEM },
169  { "Disable my target", 300, DISABLE_TARGET_ITEM },
170  { "Disarm my target", 301, DISARM_TARGET_ITEM },
171  { "Destroy subsystem", 302, DISABLE_SUBSYSTEM_ITEM },
172  { "Protect my target", 303, PROTECT_TARGET_ITEM },
173  { "Ignore my target", 304, IGNORE_TARGET_ITEM },
174  { "Form on my wing", 305, FORMATION_ITEM },
175  { "Cover me", 306, COVER_ME_ITEM },
176  { "Engage enemy", 307, ENGAGE_ENEMY_ITEM },
177 
178  // transports mostly
179  { "Capture my target", 308, CAPTURE_TARGET_ITEM },
180 
181  // support ships
182  { "Rearm me", 309, REARM_REPAIR_ME_ITEM },
183  { "Abort rearm", 310, ABORT_REARM_REPAIR_ITEM },
184 
185  // all ships
186  { "Depart", 311, DEPART_ITEM },
187 
188  // extra stuff for support (maintain original comm menu order)
189  { "Stay near me", -1, STAY_NEAR_ME_ITEM},
190  { "Stay near my target",-1, STAY_NEAR_TARGET_ITEM},
191  { "Keep safe distance", -1, KEEP_SAFE_DIST_ITEM},
192  };
193 
195 {
196  int i;
197 
198  const char *temp_comm_order_types[] =
199  {
200  XSTR("Ships", 293),
201  XSTR("Wings", 294),
202  XSTR("All Fighters", 295),
203  XSTR("Reinforcements", 296),
204  XSTR("Rearm/Repair Subsys", 297),
205  XSTR("Abort Rearm", 298)
206  };
207 
208  for (i = 0; i < NUM_COMM_ORDER_TYPES; i++)
209  {
210  strcpy_s(Comm_order_types[i], temp_comm_order_types[i]);
211  }
212 
213  for (i = 0; i < NUM_COMM_ORDER_ITEMS; i++)
214  {
215  strcpy_s(Comm_orders[i].name, XSTR(Sexp_comm_orders[i].name, Sexp_comm_orders[i].xstring));
216  Comm_orders[i].item = Sexp_comm_orders[i].item;
217  }
218 }
219 
220 // Text to display on the messaging menu when using the shortcut keys
221 char *comm_order_get_text(int item)
222 {
223  int i;
224 
225  for (i = 0; i < NUM_COMM_ORDER_ITEMS; i++)
226  {
227  if (Comm_orders[i].item == item)
228  return Comm_orders[i].name;
229  }
230 
231  // not found
232  Int3();
233  return NULL;
234 }
235 
237 
238 // forward declarations
239 void hud_add_issued_order(char *name, int order);
240 void hud_update_last_order(char *target, int order_source, int special_index);
241 int hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip = NULL );
242 int hud_squadmsg_ship_order_valid( int shipnum, int order );
243 
244 // function to set up variables needed when messaging mode is started
246 {
247 // int i;
248 
249  //if ( num_keys_saved < 0 ) // save the keys if they haven't been saved yet
251 
252  Msg_key = -1;
253 
254 /*
255  for (i=0; i<num_keys_saved; i++)
256  clear_key_binding ( (short) key_save[i].key_value ); // removes all mention of this key from Control_config
257 */
258 
259  Num_menu_items = -1; // reset the menu items
260  First_menu_item = 0;
261  Squad_msg_mode = SM_MODE_TYPE_SELECT; // start off at the base state
262  Msg_mode_timestamp = timestamp(DEFAULT_MSG_TIMEOUT); // initialize our timer to bogus value
263  Msg_shortcut_command = -1; // assume no shortcut key being used
264  Msg_target_objnum = Player_ai->target_objnum; // save the players target object number
265  Msg_targeted_subsys = Player_ai->targeted_subsys; // save the players currently targted subsystem
266 #ifndef NDEBUG
267  Msg_enemies = 0; // tells us if we are messaging enemy ships
268 #endif
269 
271 }
272 
273 // functions which will restore all of the key binding stuff when messaging mode is done
275 {
276 /*
277  int i;
278  key_store *ksp;
279 
280  // move through all keys saved and restore their orignal values.
281  for ( i=0; i<num_keys_saved; i++ ) {
282  ksp = &key_save[i];
283  Control_config[ksp->option_num].key_id = (short) ksp->key_value;
284  }
285 */
286 
287  if ( message_is_playing() == FALSE )
289 }
290 
291 // function which returns true if there are fighters/bombers on the players team in the mission
292 // In debug versions, we will allow messaging to enemies
294 {
295  ship_obj *so;
296  object *objp;
297  ship *shipp;
298 
299  for (so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so))
300  {
301  objp = &Objects[so->objnum];
302  shipp = &Ships[objp->instance];
303  Assert ( shipp->objnum != -1 );
304 
305  // check fighter is accepting orders
306  if (shipp->orders_accepted == 0)
307  continue;
308 
309  // be sure ship is on correct team
310 #ifdef NDEBUG
311  if (shipp->team != Player_ship->team)
312  continue;
313 #else
314  if (!Msg_enemies && (shipp->team != Player_ship->team))
315  continue;
316 #endif
317 
318  // cannot be my ship or an instructor
319  if ((objp == Player_obj) || is_instructor(objp))
320  continue;
321 
322  // ship must be a fighter/bomber
323  if ( !(Ship_info[shipp->ship_info_index].flags & (SIF_FIGHTER | SIF_BOMBER)) )
324  continue;
325 
326  // this ship satisfies everything
327  return true;
328  }
329 
330  return false;
331 }
332 
333 // Routine to return true if a ship should be put onto the messaging menu. Analagous to hud_squadmsg_wing_valid() below. -MageKing17
335 {
336  Assertion(shipp != nullptr, "hud_squadmsg_ship_valid() was passed a null shipp pointer; get a coder!\n");
337  if (!objp) // For simplicity's sake, allow it to be called with just the ship pointer
338  objp = &Objects[shipp->objnum];
339 
340  // ships must be able to receive a message
341  if ( Ship_info[shipp->ship_info_index].class_type < 0 || !(Ship_types[Ship_info[shipp->ship_info_index].class_type].ai_bools & STI_AI_ACCEPT_PLAYER_ORDERS) )
342  return false;
343 
344  // be sure ship is on correct team
345 #ifdef NDEBUG
346  if (shipp->team != Player_ship->team)
347  return false;
348 #else
349  if (!Msg_enemies && (shipp->team != Player_ship->team))
350  return false;
351 #endif
352 
353  // departing or dying ships cannot be on list
354  if ( shipp->flags & (SF_DEPARTING|SF_DYING) )
355  return false;
356 
357  // cannot be my ship or an instructor
358  if ((objp == Player_obj) || is_instructor(objp))
359  return false;
360 
361  // ship must be accepting ship type orders
362  if ( shipp->orders_accepted == 0)
363  return false;
364 
365  // if it is a player ship, we must be in multiplayer
366  if ( (objp->flags & OF_PLAYER_SHIP) && !(Game_mode & GM_MULTIPLAYER) )
367  return false;
368 
369  // if a messaging shortcut, be sure this ship can process the order
370  if ( Msg_shortcut_command != -1 ) {
371  if ( !(shipp->orders_accepted & Msg_shortcut_command) )
372  return false;
374  return false;
375  }
376 
377  // If we got to this point, the ship must be valid.
378  return true;
379 }
380 
381 // function which counts the number of ships available for messaging. Used to determine if
382 // we should grey out a menu or allow a shortcut command to apply. parameter "flag" is used
383 // to tell us whether or not we should add the ship to a menu item or not. We include the
384 // flag so that we don't have to have conditions for messaging ships/wings in two places.
385 int hud_squadmsg_count_ships(int add_to_menu)
386 {
387  int count;
388  ship_obj *so;
389  object *objp;
390  ship *shipp;
391 
392  count = 0;
393  for (so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so))
394  {
395  objp = &Objects[so->objnum];
396  shipp = &Ships[objp->instance];
397  Assertion(shipp->objnum != -1, "hud_squadmsg_count_ships() discovered that ship #%d ('%s') has an objnum of -1. Since the ship was retrieved from its object number (%d), this should be impossible; get a coder!\n", objp->instance, shipp->ship_name, so->objnum);
398 
399  if (!hud_squadmsg_ship_valid(shipp, objp))
400  continue;
401 
402  // this ship satisfies everything
403  count++;
404  if (add_to_menu)
405  {
407  strcpy_s( MsgItems[Num_menu_items].text, shipp->ship_name );
408  end_string_at_first_hash_symbol(MsgItems[Num_menu_items].text); // truncate the name if it has a # in it
409  MsgItems[Num_menu_items].instance = SHIP_INDEX(shipp);
410  MsgItems[Num_menu_items].active = 1;
411  Num_menu_items++;
412  }
413  }
414 
415  // if adding to the menu and we have > 10 items, then don't allow page up and page down to be used.
416  if ( add_to_menu && (Num_menu_items > MAX_MENU_DISPLAY) )
418 
419  return count;
420 }
421 
422 // routine to return true if a wing should be put onto the messaging menu
424 {
425  int idx, ship_num;
426 
427  // a couple of special cases to account for before adding to count (or to menu). Don't count
428  // wings that are leaving or left.
429  if ( wingp->flags & (WF_WING_GONE|WF_WING_DEPARTING) )
430  return 0;
431 
432  // Goober5000 - instead of checking wing leader, let's check all ships in wing;
433  // there are several significant cases when e.g. wings contain ships of different IFFs
434  for (idx = 0; idx < wingp->current_count; idx++)
435  {
436  ship_num = wingp->ship_index[idx];
437  Assert(ship_num >= 0);
438 
439  // don't check player
440  if (ship_num == SHIP_INDEX(Player_ship))
441  continue;
442 
443  // be sure ship is on same team
444 #ifdef NDEBUG
445  if (Ships[ship_num].team != Player_ship->team)
446  continue;
447 #else
448  if (!Msg_enemies && (Ships[ship_num].team != Player_ship->team))
449  continue;
450 #endif
451 
452  // check if ship is accepting orders
453  if (Ships[ship_num].orders_accepted == 0)
454  continue;
455 
456  // if doing a message shortcut is being used, be sure the ship can "accept" the command.
457  if ( Msg_shortcut_command >= 0 && !(Ships[ship_num].orders_accepted & Msg_shortcut_command) )
458  return 0;
459 
460 
461  // at least one ship in this wing is valid, and that's all we need
462  return 1;
463  }
464 
465  // no ships in the wing were valid
466  return 0;
467 }
468 
469 // function like above, except for wings
470 int hud_squadmsg_count_wings( int add_to_menu )
471 {
472  int count, i, j;
473 
474  count = 0;
475 
476  // add the player starting wings first
477  for ( i = 0; i < MAX_STARTING_WINGS; i++ ) {
478  int wingnum;
479 
480  wingnum = Starting_wings[i];
481  if ( wingnum == -1 )
482  continue;
483 
484  if ( hud_squadmsg_wing_valid(&Wings[wingnum]) ) {
485  count++;
486  if ( add_to_menu ) {
488  strcpy_s( MsgItems[Num_menu_items].text, Wings[wingnum].name );
490  MsgItems[Num_menu_items].instance = wingnum;
491  MsgItems[Num_menu_items].active = 1;
492  Num_menu_items++;
493  }
494  }
495  }
496 
497  for ( i = 0; i < Num_wings; i++ ) {
498  // if this wing is a player starting wing, skip it since we added it above
499  for ( j = 0; j < MAX_STARTING_WINGS; j++ ) {
500  if ( i == Starting_wings[j] )
501  break;
502  }
503  if ( j < MAX_STARTING_WINGS )
504  continue;
505 
506  if ( hud_squadmsg_wing_valid(&Wings[i]) ) {
507  count++;
508  if ( add_to_menu ) {
510  strcpy_s( MsgItems[Num_menu_items].text, Wings[i].name );
512  MsgItems[Num_menu_items].instance = i;
513  MsgItems[Num_menu_items].active = 1;
514  Num_menu_items++;
515  }
516  }
517  }
518  return count;
519 }
520 
521 
522 // function to set the current submode in message mode -- also resets variables that
523 // should be reset inbetween submodes
525 {
527  Num_menu_items = -1;
528  First_menu_item = 0;
529 }
530 
532 {
536  }
537 }
538 
540 {
541  if ( First_menu_item > 0 ) {
543  Assert (First_menu_item >= 0 );
544  }
545 }
546 
548 {
549  int num_keys_used;
550 
551  num_keys_used = MAX_KEYS_NO_SCROLL;
553  num_keys_used = MAX_KEYS_USED;
554 
555  return num_keys_used;
556 }
557 
558 // function called from high level keyboard read code to give the squadmsg code a key.
559 // return 1 is the key was used by the messaging code, 0 otherwise
561 {
562  int i, key_found, num_keys_used;
563 
564  num_keys_used = hud_squadmsg_get_total_keys();
565 
566  if ( !(Player->flags & PLAYER_FLAGS_MSG_MODE) ) {
567  // check to see if any messaging keys are still down for some length of time
568  // after messaging is over. Return true for a while.
570  for (i = 0; i < num_keys_used; i++ ) {
571  if ( keyd_pressed[keys_used[i]] )
572  return 1;
573  }
574  }
575 
576  return 0;
577  }
578 
579  key_found = 0;
580  for (i = 0; i < num_keys_used; i++ ) {
581  if ( k == keys_used[i] ) {
582  if ( key_down_count(k) ) {
583  Msg_key = k;
584  key_found = 1;
585  }
586 
587  if ( keyd_pressed[k] ) {
588  key_found = 1;
589  }
590 
591 // key_down_count(k);
592  break;
593  }
594  }
595 
596  if ( key_found )
597  return 1;
598 
599  return 0;
600 }
601 
602 // function which reads the keyboard array and determines if a menu key has been hit
604 {
605  int k, i, num_keys_used;
606 
607  if ( Msg_key == -1 )
608  return -1;
609 
610  k = Msg_key;
611  Msg_key = -1;
612 
613  num_keys_used = hud_squadmsg_get_total_keys();
614 
615  // if the emp effect is active, never accept keypresses
616  if(emp_active_local()){
617  return -1;
618  }
619 
620  for ( i = 0; i < num_keys_used; i++ ) {
621  if ( k == keys_used[i] ) {
622  Msg_key_used = 1; // this variable will extend the timer
623 
624  // use a timestamp to prevent top level key code from possibly reprocessing this key
626  if ( k == KEY_PAGEDOWN ) { // pageup and pagedown scroll the menu -- deal with these seperately!!
628  return -1;
629  } else if ( k == KEY_PAGEUP ) {
631  return -1;
632  } else if ( k == KEY_ESC ) {
634  return -1;
635  } else if ( (i < Num_menu_items) && (Squad_msg_mode == SM_MODE_REINFORCEMENTS) ) // return any key if selecting reinforcement
636  return i;
637 
638  // play general fail sound if inactive item hit.
639  else if ( (i < Num_menu_items) && !(MsgItems[i].active) )
641 
642  else if ( (i < Num_menu_items) && (MsgItems[i].active) ) // only return keys that are associated with menu items
643  return i;
644 
645  else {
646  Msg_key_used = 0; // if no #-key pressed for visible item, break and allow timer to
647  break; // to continue as if no key was pressed
648  }
649  }
650  }
651 
652  return -1;
653 }
654 
655 // function to return true or false if the given ship can rearm, or be repaired
657 {
658  // player ships which turns traitor cannot rearm
659  if ( (shipp == Player_ship) && (Player_ship->team == Iff_traitor) )
660  return 0;
661 
662  // 5/6/98 -- MWA Decided to always be able to call in support.
663  return 1;
664 }
665 
666 // calls for repair/rearm of the player ship. Checks for the presence of the support
667 // ship and does the appropriate action if found
668 void hud_squadmsg_repair_rearm( int toggle_state, object *objp)
669 {
670  int robjnum;
671  object *robjp;
672  object *tobj;
673  int multi_player_num;
674  int multi_player_team;
675 
676  // this is essentially a check for multiplayer server/client mode
677  // in multiplayer mode, the server may have to issue this command when received from a client
678  if(objp == NULL) {
679  tobj = Player_obj;
680  multi_player_num = -1;
681  multi_player_team = -1;
682  } else {
683  tobj = objp;
684  multi_player_num = multi_find_player_by_object(objp);
685  Assert(multi_player_num != -1);
686  if (multi_player_num != -1) {
687  multi_player_team = Net_players[multi_player_num].p_info.team;
688  }
689  else {
690  multi_player_team = -1;
691  }
692  }
693 
694  // see if player is already scheduled on arriving support ship. If so, issues appripriate
695  // message and bail
696  if ( is_support_allowed(tobj) ) {
697  if ( mission_is_repair_scheduled( tobj ) ) {
698  message_send_builtin_to_player( MESSAGE_REARM_ON_WAY, NULL, MESSAGE_PRIORITY_NORMAL, MESSAGE_TIME_SOON, 0, 0, multi_player_num, multi_player_team );
699  } else {
700  robjnum = hud_support_find_closest(OBJ_INDEX(tobj));
701  if ( robjnum != -1 ) {
702  message_send_builtin_to_player( MESSAGE_REARM_ON_WAY, &Ships[Objects[robjnum].instance], MESSAGE_PRIORITY_NORMAL, MESSAGE_TIME_SOON, 0, 0, multi_player_num, multi_player_team );
703  } else {
704  // request a rearm. Next function returns -1 if ship is warping in, objnum of repair ship otherwise
705  robjnum = ai_issue_rearm_request( tobj );
706  if ( robjnum != -1) {
707  robjp = &Objects[robjnum];
708  message_send_builtin_to_player( MESSAGE_ON_WAY, &Ships[robjp->instance], MESSAGE_PRIORITY_NORMAL, MESSAGE_TIME_SOON, 0, 0, multi_player_num, multi_player_team );
709 
710  } else {
711  // if we are in this part of the if statement, a support ship has been warped in to
712  // service us. Issue appropriate message
713  message_send_builtin_to_player( MESSAGE_REARM_WARP, NULL, MESSAGE_PRIORITY_NORMAL, MESSAGE_TIME_SOON, 0, 0, multi_player_num, multi_player_team );
714  }
715 
717  }
718  }
719  }
720 
721  //if ( multi_player_num == -1 ) // only do the hud display if it is for me!
722  // hud_support_view_start();
723 
724  if ( toggle_state )
725  hud_squadmsg_toggle(); // take us out of message mode
726 }
727 
728 // function which gets called from keyboard code to issues a shortcut command for rearming.
730 {
732  return;
733 
734  // multiplayer clients need to send this message to the server
735  if ( MULTIPLAYER_CLIENT ) {
737  return;
738  }
739 
741 }
742 
743 // code which is called when a player aborts his rearm request
744 void hud_squadmsg_repair_rearm_abort( int toggle_state, object *obj)
745 {
746 // ai_info *aip;
747 // object *robjp;
748  object *tobj;
749 
750  // this is essentially a check for multiplayer server/client mode
751  // in multiplayer mode, the server may have to issue this command when received from a client
752  if(obj == NULL)
753  tobj = Player_obj;
754  else
755  tobj = obj;
756 
757  // try to abort the request. We shoudln't be in this function unless we are actually
758  // queued for repair. Send a message from support ship if the support ship is in the mission
759  ai_abort_rearm_request( tobj );
760 
761  // move the next statements outside of the above if-statement. Seems like this place
762  // is the right place, since we want to change state of the messaging system regardless
763  // of what happened above.
764  if ( toggle_state )
765  hud_squadmsg_toggle(); // take us out of message mode
766 }
767 
768 // Goober5000 - redone and added a bit
769 // returns 1 if an order is valid for a ship. Applies to things like departure when engines are blown, etc.
770 int hud_squadmsg_ship_order_valid( int shipnum, int order )
771 {
772  // Goober5000
773  Assert( shipnum >= 0 && shipnum < MAX_SHIPS );
774  ship *shipp = &Ships[shipnum];
775 
776  switch ( order )
777  {
778  case DEPART_ITEM:
779  // disabled ships can't depart.
780  if (shipp->flags & SF_DISABLED)
781  return 0;
782 
783  // Goober5000: also can't depart if no subspace drives and no valid mothership
784  if (shipp->flags2 & SF2_NO_SUBSPACE_DRIVE)
785  {
786  // check that we have a mothership and that we can depart to it
788  {
789  int anchor_shipnum = ship_name_lookup(Parse_names[shipp->departure_anchor]);
790  if (anchor_shipnum >= 0 && ship_useful_for_departure(anchor_shipnum, shipp->departure_path_mask))
791  return 1;
792  }
793 
794  return 0;
795  }
796 
797  break;
798  }
799  return 1;
800 }
801 
802 // returns true or false if the Players target is valid for the given order
803 // find_order is true when we need to search the comm_orders array for the order entry. We have
804 // to do this action in some cases since all we know is the actual "value" of the order
805 int hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip )
806 {
807  int target_objnum, i;
808  ship *shipp, *ordering_shipp;
809  object *objp;
810 
811  if ( aip == NULL )
812  aip = Player_ai;
813 
814  // find the comm_menu item for this command
815  if ( find_order ) {
816  for (i = 0; i < NUM_COMM_ORDER_ITEMS; i++ ) {
817  if ( Comm_orders[i].item == order )
818  break;
819  }
820  Assert( i < NUM_COMM_ORDER_ITEMS );
821  order = i;
822  }
823 
824  // orders which don't operate on targets are always valid
825  if ( !(Comm_orders[order].item & TARGET_MESSAGES) )
826  return 1;
827 
828  target_objnum = aip->target_objnum;
829 
830  // order isn't valid if there is no player target
831  if ( target_objnum == -1 ) {
832  return 0;
833  }
834 
835  objp = &Objects[target_objnum];
836 
837  ordering_shipp = &Ships[aip->shipnum];
838 
839  // target isn't a ship, then return 0
840  if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_WEAPON) )
841  return 0;
842 
843  // if it's a weapon, then it needs to be a WIF_BOMB weapon. Only attack order valid, and only
844  // valid on bombs not on the player's team
845  // MageKing17: Now also works on WIF3_FIGHTER_INTERCEPTABLE weapons.
846  if ( objp->type == OBJ_WEAPON ) {
847 
848  if (Weapons[objp->instance].lssm_stage==3){
849  return 0;
850  }
851 
852  if ( (Comm_orders[order].item == ATTACK_TARGET_ITEM )
854  && (Weapons[objp->instance].team != ordering_shipp->team) )
855 
856  return 1;
857 
858  return 0;
859  }
860 
861  Assert( objp->type == OBJ_SHIP );
862 
863  shipp = &Ships[objp->instance];
864 
865  // if target is a navbouy, return 0
866  if ( Ship_info[shipp->ship_info_index].flags & SIF_NAVBUOY ){
867  return 0;
868  }
869 
870  // if we are messaging a ship, and that ship is our target, no target type orders are ever active
871  if ( (Squad_msg_mode == SM_MODE_SHIP_COMMAND) && (Objects[target_objnum].instance == Msg_instance) ){
872  return 0;
873  }
874 
875  // if the order is a disable order or depart, and the ship is disabled, order isn't active
876  if ( (Comm_orders[order].item == DISABLE_TARGET_ITEM) && (shipp->flags & SF_DISABLED) ){
877  return 0;
878  }
879 
880  // same as above except for disarmed.
881  if ( (Comm_orders[order].item == DISARM_TARGET_ITEM) && ((shipp->subsys_info[SUBSYSTEM_TURRET].type_count == 0) || (shipp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f)) ){
882  return 0;
883  }
884 
885  // if order is disable subsystem, and no subsystem targeted or no hits, then order not valid
886  if ( (Comm_orders[order].item == DISABLE_SUBSYSTEM_ITEM) && ((aip->targeted_subsys == NULL) || (aip->targeted_subsys->current_hits <= 0.0f)) ){
887  return 0;
888  }
889 
890  // check based on target's and player's team
891  if ( (shipp->team == ordering_shipp->team) && (FRIENDLY_TARGET_MESSAGES & Comm_orders[order].item) ){
892  return 1;
893  } else if ( (shipp->team != ordering_shipp->team) && (ENEMY_TARGET_MESSAGES & Comm_orders[order].item) ){
894  return 1;
895  } else {
896  return 0;
897  }
898 }
899 
900 // function to send an order to all fighters/bombers.
901 void hud_squadmsg_send_to_all_fighters( int command, int player_num )
902 {
903  ai_info *aip;
904  ship *shipp, *ordering_shipp;
905  int i, send_message;
906  object *objp;
907 
908  // quick short circuit here because of actually showing comm menu even though you cannot message.
909  // just a safety net.
910  if ( (Game_mode & GM_MULTIPLAYER) && (player_num != -1) ) {
911  if ( !multi_can_message(&Net_players[player_num]) ) {
912  return;
913  }
914  }
915 
916  // check for multiplayer mode
917  if(MULTIPLAYER_CLIENT) {
919  return;
920  }
921 
922  send_message = 1; // internal flag to dictate who sends message
923  aip = Player_ai;
924 
925  if ( player_num != -1 )
927 
928  Assert( aip->shipnum != -1 );
929  ordering_shipp = &Ships[aip->shipnum];
930 
931  /* Goober5000 - this relies on the weird calling logic that is now disabled
932  if ( command == IGNORE_TARGET_ITEM ) {
933  // if we were messaging a ship directly, set flag to send no messages. We will send one
934  // specifically from the ship player is ordering
935  if ( (Msg_instance != MESSAGE_ALL_FIGHTERS) && (Squad_msg_mode == SM_MODE_SHIP_COMMAND) ) {
936  do_ship = 1;
937  send_message = 0;
938  }
939  }
940  */
941 
942  for ( i = 0; i < Num_wings; i++ ) {
943  int shipnum;
944 
945  if ( (Wings[i].flags & WF_WING_GONE) || (Wings[i].current_count == 0) )
946  continue;
947 
948  if ( Wings[i].flags & WF_WING_DEPARTING )
949  continue;
950 
951  // get the first ship on the wing list and look at its team and then its type
952  shipnum = Wings[i].ship_index[Wings[i].special_ship];
953 
954  // if special ship isn't valid then just move on
955  if (shipnum < 0)
956  continue;
957 
958  shipp = &Ships[shipnum];
959 
960  // can't message if not on players team
961  if ( shipp->team != ordering_shipp->team )
962  continue;
963 
964  // can't message if ship not fighter/bomber if the command isn't to everyone.
965  if ( !(Ship_info[shipp->ship_info_index].flags & (SIF_FIGHTER | SIF_BOMBER)) )
966  continue;
967 
968  // don't send the command if the "wing" won't accept the command. We do this by looking at
969  // the set of orders accepted for the wing leader
970  if ( !(command & shipp->orders_accepted) )
971  continue;
972 
973  // send the command to the wing
974  if ( Wings[i].current_count > 0 ) {
975  if (send_message) {
976  hud_add_issued_order("All Fighters", command);
977  if ( hud_squadmsg_send_wing_command(i, command, send_message, SQUADMSG_HISTORY_UPDATE, player_num) ) {
978  send_message = 0;
979  }
980  }
981  else {
982  hud_squadmsg_send_wing_command(i, command, send_message, SQUADMSG_HISTORY_NO_UPDATE, player_num);
983  }
984  }
985  }
986 
987  // now find any friendly fighter/bomber ships not in wings
988  for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
989  if ( objp->type != OBJ_SHIP )
990  continue;
991 
992  // don't send messge to ships not on player's team, or that are in a wing.
993  shipp = &Ships[objp->instance];
994  if ( (shipp->team != ordering_shipp->team) || (shipp->wingnum != -1) )
995  continue;
996 
997  // don't send message to non fighter wings
998  if ( !(Ship_info[shipp->ship_info_index].flags & (SIF_FIGHTER | SIF_BOMBER)) )
999  continue;
1000 
1001  // skip departing/dying ships
1002  if ( shipp->flags & (SF_DEPARTING|SF_DYING) )
1003  continue;
1004 
1005  // don't send command if ship won't accept if
1006  if ( !(command & shipp->orders_accepted) )
1007  continue;
1008 
1009  if (send_message) {
1010  hud_add_issued_order("All Fighters", command);
1011  if ( hud_squadmsg_send_ship_command(objp->instance, command, send_message, SQUADMSG_HISTORY_UPDATE, player_num) ) {
1012  send_message = 0;
1013  }
1014  }
1015  else {
1016  hud_squadmsg_send_ship_command(objp->instance, command, send_message, SQUADMSG_HISTORY_NO_UPDATE, player_num);
1017  }
1018  }
1019 
1020  // we might send the ship command again if we are ignoring a target, and the guy
1021  // we ordered directly is a ship -- we want the response to come directly from the
1022  // guy we orders
1023  /* Goober5000 - yet again with the weird logic
1024  if ( do_ship ) {
1025  Assert( Msg_instance != MESSAGE_ALL_FIGHTERS );
1026  hud_squadmsg_send_ship_command( Msg_instance, command, 1 );
1027  }
1028  */
1029 }
1030 
1031 // Check if any enemy ships are in the mission
1033 {
1034  ship *shipp;
1035  ship_obj *so;
1036 
1037  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
1038  shipp = &Ships[Objects[so->objnum].instance];
1039  if ( shipp->team != Player_ship->team )
1040  return 1;
1041  }
1042 
1043  return 0;
1044 }
1045 
1046 #define OVERRIDE_PROTECT_SHIP_TYPE (SIF_FIGHTER|SIF_BOMBER|SIF_FREIGHTER|SIF_TRANSPORT)
1047 // function which sends a message to a specific ship. This routine can be called from one of two
1048 // places. Either after selecting a ship when using a hotkey, or after selecting a command when
1049 // using the entire messaging menu system
1050 //
1051 // if local and addr are non-null, it means the function is being called by the (multiplayer) server in response to
1052 // a PLAYER_COMMAND_PACKET
1053 int hud_squadmsg_send_ship_command( int shipnum, int command, int send_message, int update_history, int player_num )
1054 {
1055  ai_info *ainfo;
1056  int ai_mode, ai_submode; // ai mode and submode needed for ship commands
1057  char *target_shipname; // ship number of possible targets
1058  int message;
1059  int target_team, ship_team; // team id's for the ship getting message and any target the player has
1060  ship *ordering_shipp;
1061 
1062  int special_index = -1;
1063  int message_team_filter = -1;
1064 
1065  // quick short circuit here because of actually showing comm menu even though you cannot message.
1066  // just a safety net.
1067  if ( (Game_mode & GM_MULTIPLAYER) && (player_num != -1) ) {
1068  if ( !multi_can_message(&Net_players[player_num]) ) {
1069  return 0;
1070  }
1071  }
1072 
1073  // check for multiplayer mode
1074  if(MULTIPLAYER_CLIENT){
1075  send_player_order_packet(SQUAD_MSG_SHIP, shipnum, command);
1076  return 0;
1077  }
1078 
1079  ai_mode = AI_GOAL_NONE; // needs to be initialized
1080  ai_submode = -1234567;
1081  ainfo = Player_ai;
1082 
1083  if ( player_num != -1 ){
1084  ainfo = &Ai_info[Ships[Objects[Net_players[player_num].m_player->objnum].instance].ai_index];
1085  message_team_filter = Net_players[player_num].p_info.team;
1086  }
1087 
1088  Assert( ainfo->shipnum != -1 );
1089  ordering_shipp = &Ships[ainfo->shipnum];
1090 
1091  // a shortcut to save on repetitive coding. If the order is a 'target' order, make the default
1092  // mesage be "no target"
1093  message = MESSAGE_NOSIR;
1094  if ( (command & TARGET_MESSAGES) && (ainfo->target_objnum == -1) )
1095  message = MESSAGE_NO_TARGET;
1096 
1097  if ( hud_squadmsg_is_target_order_valid(command, 1, ainfo) ) {
1098 
1099  target_shipname = NULL;
1100  target_team = -1;
1101  if ( ainfo->target_objnum != -1) {
1102  if ( Objects[ainfo->target_objnum].type == OBJ_SHIP ) {
1103  if ( ainfo->target_objnum != Ships[shipnum].objnum ) {
1104  target_shipname = Ships[Objects[ainfo->target_objnum].instance].ship_name; // I think this is right
1105  target_team = Ships[Objects[ainfo->target_objnum].instance].team;
1106  }
1107  }
1108  }
1109 
1110  Assert ( ainfo->shipnum != -1 );
1111  ship_team = Ships[ainfo->shipnum].team; // team of the ship issuing the message
1112 
1113  switch ( command ) { // value of k matches the #defines for ship messages
1114  case ATTACK_TARGET_ITEM:
1115  if ( Objects[ainfo->target_objnum].type == OBJ_SHIP ) {
1116  Assert( target_shipname );
1117  Assert( ship_team != target_team );
1118 
1119  // Orders to override protect
1122  }
1123 
1124  ai_mode = AI_GOAL_CHASE;
1125  ai_submode = SM_ATTACK;
1126  } else if ( Objects[ainfo->target_objnum].type == OBJ_WEAPON ) {
1127  ai_mode = AI_GOAL_CHASE_WEAPON;
1128  ai_submode = Objects[ainfo->target_objnum].instance; // store the instance of the weapon -- ai goals code will deal with it
1129  } else
1130  Int3();
1131  message = MESSAGE_ATTACK_TARGET;
1132  break;
1133 
1134  case DISABLE_TARGET_ITEM:
1135  Assert( target_shipname );
1136  Assert( ship_team != target_team );
1137 
1138  // Orders to override protect
1141  }
1142 
1143  ai_mode = AI_GOAL_DISABLE_SHIP;
1144  ai_submode = -SUBSYSTEM_ENGINE;
1145  message = MESSAGE_DISABLE_TARGET;
1146  break;
1147 
1148  case DISARM_TARGET_ITEM:
1149  Assert( target_shipname );
1150  Assert( ship_team != target_team );
1151 
1152  // Orders to override protect
1153  if (Ship_info[Ships[Objects[ainfo->target_objnum].instance].ship_info_index].flags & OVERRIDE_PROTECT_SHIP_TYPE) {
1155  }
1156 
1157  ai_mode = AI_GOAL_DISARM_SHIP;
1158  ai_submode = -SUBSYSTEM_TURRET;
1159  message = MESSAGE_DISARM_TARGET;
1160  break;
1161 
1163  Assert( target_shipname );
1164  Assert( ship_team != target_team );
1165  Assert( ainfo->targeted_subsys != NULL );
1166  Assert( ainfo->targeted_subsys->current_hits > 0.0f);
1167 
1168  // Orders to override protect
1169  if (Ship_info[Ships[Objects[ainfo->target_objnum].instance].ship_info_index].flags & OVERRIDE_PROTECT_SHIP_TYPE) {
1171  }
1172 
1173  ai_mode = AI_GOAL_DESTROY_SUBSYSTEM;
1175  special_index = ai_submode;
1176  message = MESSAGE_ATTACK_TARGET;
1177  break;
1178 
1179  case CAPTURE_TARGET_ITEM:
1180  Assert( target_shipname );
1181  Assert( ship_team != target_team );
1182 
1183  Assert(ainfo->target_objnum > -1);
1184 
1185  Objects[ainfo->target_objnum].flags |= OF_PROTECTED;
1186 
1187  ai_mode = AI_GOAL_DOCK;
1188  ai_submode = AIS_DOCK_0;
1189  message = MESSAGE_DOCK_YES;
1190  break;
1191 
1192  case PROTECT_TARGET_ITEM:
1193 
1194  // AL 31-3-98: Can't protect self... this can happen if all fighters
1195  // are told to protect another friendly ship
1196  if ( ainfo->target_objnum == Ships[shipnum].objnum ) {
1197  return 0;
1198  }
1199 
1200  Assert( target_shipname );
1201  Assert( ship_team == target_team );
1202 
1203  ai_mode = AI_GOAL_GUARD;
1204  ai_submode = AIS_GUARD_PATROL;
1205  message = MESSAGE_YESSIR;
1206  break;
1207 
1208  case IGNORE_TARGET_ITEM:
1209  Assert( target_shipname );
1210  Assert( ship_team != target_team );
1211 
1212  ai_mode = AI_GOAL_IGNORE_NEW;
1213  ai_submode = 0;
1214  message = MESSAGE_IGNORE;
1215  break;
1216 
1217  case FORMATION_ITEM:
1218  message = MESSAGE_YESSIR;
1219  target_shipname = ordering_shipp->ship_name;
1220  ai_mode = AI_GOAL_FORM_ON_WING;
1221  ai_submode = 0;
1222  break;
1223 
1224  case COVER_ME_ITEM:
1225  ai_mode = AI_GOAL_GUARD;
1226  ai_submode = AIS_GUARD_PATROL;
1227  target_shipname = ordering_shipp->ship_name;
1228  message = MESSAGE_YESSIR;
1229  break;
1230 
1231  case ENGAGE_ENEMY_ITEM:
1232  ai_mode = AI_GOAL_CHASE_ANY;
1233  ai_submode = SM_ATTACK;
1234  // if no enemies present, use the affirmative, instead of engaging enemies message
1236  message = MESSAGE_ENGAGE;
1237  else
1238  message = MESSAGE_YESSIR;
1239  target_shipname = NULL;
1240  break;
1241 
1242  case DEPART_ITEM:
1243  ai_mode = AI_GOAL_WARP;
1244  ai_submode = -1;
1245  message = MESSAGE_WARP_OUT;
1246  Ships[shipnum].flags |= SF_DEPARTURE_ORDERED;
1247  break;
1248 
1249  // the following are support ship options!!!
1250  case REARM_REPAIR_ME_ITEM:
1251  if( MULTIPLAYER_MASTER && (player_num != -1) ){
1252  hud_squadmsg_repair_rearm(0,&Objects[Net_players[player_num].m_player->objnum]);
1253  } else {
1254  hud_squadmsg_repair_rearm(0); // note we return right away. repair/rearm code handles messaging, etc
1255  }
1256  // add the order to the squad message history
1257  hud_add_issued_order(Ships[shipnum].ship_name, command);
1258  hud_update_last_order(ordering_shipp->ship_name, player_num, special_index);
1259  return 0;
1260 
1262  if( MULTIPLAYER_MASTER && (player_num != -1) ){
1263  hud_squadmsg_repair_rearm_abort(0,&Objects[Net_players[player_num].m_player->objnum]);
1264  } else {
1265  hud_squadmsg_repair_rearm_abort(0); // note we return right away. repair/rearm code handles messaging, etc
1266  }
1267  // add the order to the squad message history
1268  hud_add_issued_order(Ships[shipnum].ship_name, command);
1269  hud_update_last_order(ordering_shipp->ship_name, player_num, special_index);
1270  return 0;
1271 
1272  case STAY_NEAR_ME_ITEM:
1273  case STAY_NEAR_TARGET_ITEM: // can't attack anything on same team
1274 
1275  // cannot stay near a hostile ship(?)
1276  if ( (command == STAY_NEAR_TARGET_ITEM) && (ship_team != target_team) )
1277  break;
1278 
1279  ai_mode = AI_GOAL_STAY_NEAR_SHIP;
1280  ai_submode = -1;
1281  message = MESSAGE_YESSIR;
1282  if ( command == STAY_NEAR_ME_ITEM )
1283  target_shipname = ordering_shipp->ship_name;
1284  break;
1285 
1286  case KEEP_SAFE_DIST_ITEM:
1287  ai_mode = AI_GOAL_KEEP_SAFE_DISTANCE;
1288  ai_submode = -1;
1289  message = MESSAGE_YESSIR;
1290  break;
1291 
1292  default:
1293  Int3(); // get Allender -- illegal message
1294  break;
1295 
1296  }
1297 
1298  // handle case of messaging one ship. Deal with messaging all fighters next.
1299  if ( ai_mode != AI_GOAL_NONE ) {
1300  Assert(ai_submode != -1234567);
1301  ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, ai_mode, ai_submode, target_shipname, &Ai_info[Ships[shipnum].ai_index] );
1302  if( update_history == SQUADMSG_HISTORY_ADD_ENTRY ) {
1303  hud_add_issued_order(Ships[shipnum].ship_name, command);
1304  hud_update_last_order(target_shipname, player_num, special_index);
1305  }
1306  else if (update_history == SQUADMSG_HISTORY_UPDATE) {
1307  hud_update_last_order(target_shipname, player_num, special_index);
1308  }
1309  }
1310  }
1311 
1312  // if we're in multiplayer mode, and we're the server, determine if this virtual squadmate order should be
1313  // sent to other players in the game as an actual "order"
1314  if((Game_mode & GM_MULTIPLAYER) && (message != MESSAGE_NOSIR)){
1315  // if the multi_msg system processed and sent this order to a player, we should not play a response
1316  if(multi_msg_eval_ship_squadmsg(shipnum,command,ainfo,player_num)){
1317  send_message = 0;
1318  }
1319  }
1320 
1321  // this is the _response_
1322  if ( send_message && (!(Ships[shipnum].flags2 & SF2_NO_BUILTIN_MESSAGES)))
1323  {
1324  message_send_builtin_to_player( message, &Ships[shipnum], MESSAGE_PRIORITY_NORMAL, MESSAGE_TIME_ANYTIME, 0, 0, player_num, message_team_filter );
1325  }
1326 
1327  return send_message;
1328 }
1329 
1330 // function to send a command to a wing. Like above function, called from one of two places
1331 //
1332 // if local and addr are non-null, it means the function is being called by the (multiplayer) server in response to
1333 // a PLAYER_COMMAND_PACKET
1334 //
1335 // returns whether or not a message was sent
1336 int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message, int update_history, int player_num )
1337 {
1338  ai_info *ainfo;
1339  int ai_mode, ai_submode; // ai mode and submode needed for ship commands
1340  char *target_shipname; // ship number of possible targets
1341  int message_sent, message;
1342  int target_team, wing_team; // team for the wing and the player's target
1343  ship *ordering_shipp;
1344 
1345  int special_index = -1;
1346  int message_team_filter = -1;
1347 
1348  // quick short circuit here because of actually showing comm menu even though you cannot message.
1349  // just a safety net.
1350  if ( (Game_mode & GM_MULTIPLAYER) && (player_num != -1) ) {
1351  if ( !multi_can_message(&Net_players[player_num]) ) {
1352  return 0;
1353  }
1354  }
1355 
1356  // check for multiplayer mode
1357  if(MULTIPLAYER_CLIENT){
1358  send_player_order_packet(SQUAD_MSG_WING, wingnum,command);
1359  return 0;
1360  }
1361 
1362  ai_mode = AI_GOAL_NONE; // needs to be initialized
1363  ai_submode = -1234567;
1364  ainfo = Player_ai;
1365 
1366  if ( player_num != -1 ) {
1367  ainfo = &Ai_info[Ships[Objects[Net_players[player_num].m_player->objnum].instance].ai_index];
1368  message_team_filter = Net_players[player_num].p_info.team;
1369  }
1370 
1371  Assert( ainfo->shipnum != -1 );
1372  ordering_shipp = &Ships[ainfo->shipnum];
1373 
1374  // get the shipnum of the ship the player has targeted. Used in enough places to do this just
1375  // once. If the ship targeted is part of the wing that was messages -- bail out!!!
1376 
1377  // a shortcut to save on repetative coding
1378  message = MESSAGE_NOSIR;
1379  if ( (command & TARGET_MESSAGES) && (ainfo->target_objnum == -1) )
1380  message = MESSAGE_NO_TARGET;
1381 
1382  if ( hud_squadmsg_is_target_order_valid(command, 1, ainfo) ) {
1383 
1384  target_shipname = NULL;
1385  target_team = -1;
1386  if ( ainfo->target_objnum != -1) {
1387  if ( Objects[ainfo->target_objnum].type == OBJ_SHIP ) {
1388  target_shipname = Ships[Objects[ainfo->target_objnum].instance].ship_name; // I think this is right
1389  target_team = Ships[Objects[ainfo->target_objnum].instance].team;
1390  }
1391  }
1392 
1393  Assert ( ainfo->shipnum != -1 );
1394  Assert ( (wingnum >= 0) && (wingnum < Num_wings) );
1395 
1396  // get the team for the wing
1397  Assert ( Wings[wingnum].ship_index[0] != -1 );
1398  wing_team = Ships[Wings[wingnum].ship_index[0]].team;
1399 
1400  switch ( command ) { // value of k matches the #defines for ship messages
1401  case ATTACK_TARGET_ITEM:
1402  if ( Objects[ainfo->target_objnum].type == OBJ_SHIP ) {
1403  Assert( target_shipname );
1404  Assert( wing_team != target_team );
1405  if ( (Ships[Objects[ainfo->target_objnum].instance].wingnum != -1) && (Ships[Objects[ainfo->target_objnum].instance].wingnum == wingnum) ) {
1406  message = MESSAGE_NOSIR;
1407  ai_mode = AI_GOAL_NONE;
1408  } else {
1409  ai_mode = AI_GOAL_CHASE;
1410  ai_submode = SM_ATTACK;
1411  message = MESSAGE_ATTACK_TARGET;
1412  }
1413  } else if ( Objects[ainfo->target_objnum].type == OBJ_WEAPON ) {
1414  ai_mode = AI_GOAL_CHASE_WEAPON;
1415  ai_submode = Objects[ainfo->target_objnum].instance; // store the instance of the weapon -- ai goals code will deal with it
1416  message = MESSAGE_ATTACK_TARGET;
1417  } else
1418  Int3();
1419 
1420  break;
1421 
1422  case DISABLE_TARGET_ITEM:
1423  Assert( target_shipname );
1424  Assert( wing_team != target_team );
1425 
1426  ai_mode = AI_GOAL_DISABLE_SHIP;
1427  ai_submode = -SUBSYSTEM_ENGINE;
1428  message = MESSAGE_DISABLE_TARGET;
1429  break;
1430 
1431  case DISARM_TARGET_ITEM:
1432  Assert( target_shipname );
1433  Assert( wing_team != target_team );
1434 
1435  ai_mode = AI_GOAL_DISARM_SHIP;
1436  ai_submode = -SUBSYSTEM_TURRET;
1437  message = MESSAGE_DISARM_TARGET;
1438  break;
1439 
1441  Assert( target_shipname );
1442  Assert( wing_team != target_team );
1443  Assert( ainfo->targeted_subsys != NULL );
1444  Assert( ainfo->targeted_subsys->current_hits > 0.0f);
1445 
1446  ai_mode = AI_GOAL_DESTROY_SUBSYSTEM;
1448  special_index = ai_submode;
1449  message = MESSAGE_ATTACK_TARGET;
1450  break;
1451 
1452 
1453  case PROTECT_TARGET_ITEM:
1454  Assert( target_shipname );
1455  Assert( wing_team == target_team );
1456 
1457  ai_mode = AI_GOAL_GUARD;
1458  ai_submode = AIS_GUARD_PATROL;
1459  message = MESSAGE_YESSIR;
1460  break;
1461 
1462  case IGNORE_TARGET_ITEM:
1463  Assert( target_shipname );
1464  Assert( wing_team != target_team );
1465 
1466  ai_mode = AI_GOAL_IGNORE_NEW;
1467  ai_submode = 0; // actually, a don't care.
1468  message = MESSAGE_IGNORE;
1469  break;
1470 
1471  case FORMATION_ITEM:
1472  message = MESSAGE_YESSIR;
1473  target_shipname = ordering_shipp->ship_name;
1474  ai_mode = AI_GOAL_FORM_ON_WING;
1475  ai_submode = 0;
1476  break;
1477 
1478  case COVER_ME_ITEM:
1479  ai_mode = AI_GOAL_GUARD;
1480  ai_submode = AIS_GUARD_PATROL;
1481  target_shipname = ordering_shipp->ship_name;
1482  message = MESSAGE_YESSIR;
1483  break;
1484 
1485  case ENGAGE_ENEMY_ITEM:
1486  ai_mode = AI_GOAL_CHASE_ANY;
1487  ai_submode = SM_ATTACK;
1488  // if no enemies present, use the affirmative, instead of engaging enemies message
1490  message = MESSAGE_ENGAGE;
1491  else
1492  message = MESSAGE_YESSIR;
1493  target_shipname = NULL;
1494  break;
1495 
1496  case DEPART_ITEM:
1497  ai_mode = AI_GOAL_WARP;
1498  ai_submode = -1;
1499  message = MESSAGE_WARP_OUT;
1500  Wings[wingnum].flags |= WF_DEPARTURE_ORDERED;
1501  break;
1502 
1503  case REARM_REPAIR_ME_ITEM:
1505  case STAY_NEAR_ME_ITEM:
1506  case STAY_NEAR_TARGET_ITEM:
1507  case KEEP_SAFE_DIST_ITEM:
1508  return 0;
1509 
1510  default:
1511  Int3(); // get Allender -- illegal message
1512  break;
1513 
1514  }
1515 
1516  if ( ai_mode != AI_GOAL_NONE ) {
1517  Assert(ai_submode != -1234567);
1518  ai_add_wing_goal_player( AIG_TYPE_PLAYER_WING, ai_mode, ai_submode, target_shipname, wingnum );
1519 
1520  if( update_history == SQUADMSG_HISTORY_ADD_ENTRY ) {
1521  hud_add_issued_order(Wings[wingnum].name, command);
1522  hud_update_last_order(target_shipname, player_num, special_index);
1523  }
1524  else if (update_history == SQUADMSG_HISTORY_UPDATE) {
1525  hud_update_last_order(target_shipname, player_num, special_index);
1526  }
1527  }
1528  }
1529 
1530  // if we're in multiplayer mode, and we're the server, determine if this virtual squadmate order should be
1531  // sent to other players in the game as an actual "order"
1532  if((Game_mode & GM_MULTIPLAYER) && (message != MESSAGE_NOSIR)){
1533  // if there's at least one ai ship which got the command, let the response come through
1534  if(multi_msg_eval_wing_squadmsg(wingnum,command,ainfo,player_num)){
1535  send_message = 0;
1536  }
1537  }
1538 
1539  // this is the _response_
1540  message_sent = 0;
1541  if ( send_message ) {
1542  int ship_num;
1543 
1544  // get a random ship in the wing to send the message to the player
1545  ship_num = ship_get_random_ship_in_wing( wingnum, SHIP_GET_UNSILENCED );
1546 
1547  // in multiplayer, its possible that all ships in a wing are players. so we'll just send from a random ship
1548  if(ship_num == -1 && (Game_mode & GM_MULTIPLAYER)){
1549  ship_num = ship_get_random_ship_in_wing(wingnum);
1550  }
1551 
1552  // only send message if ship is found. There appear to be cases where all ships
1553  // in a wing die in the same frame causing the wing to appear valid in the message
1554  // menu, but the get_random_ship* functions won't return dying ships.
1555  // Karajorma - No valid ships will be found if all the remaining ships have been silence either.
1556  if ( ship_num != -1 ) {
1557  message_send_builtin_to_player( message, &Ships[ship_num], MESSAGE_PRIORITY_NORMAL, MESSAGE_TIME_ANYTIME, 0, 0, player_num, message_team_filter );
1558  message_sent = 1;
1559  }
1560  }
1561 
1562  return message_sent;
1563 }
1564 
1565 
1566 // return number of available reinforcements, 0 if none available
1568 {
1569  int i, count = 0;
1570 
1571  for (i = 0; i < Num_reinforcements; i++) {
1572  int wingnum;
1573 
1574  // no more left
1575  if ( Reinforcements[i].num_uses >= Reinforcements[i].uses ){
1576  continue;
1577  }
1578 
1579  // incorrect team
1580  if ( team != ship_get_reinforcement_team(i) ){
1581  continue;
1582  }
1583 
1584  // check the arrival cue sexpression of the ship/wing of this reinforcement.
1585  // Goober5000 - if it can't arrive, it doesn't count. This should check
1586  // for SEXP_FALSE as well as SEXP_KNOWN_FALSE, otherwise you end up with
1587  // a reinforcement menu containing no valid selections.
1588  if ( (wingnum = wing_name_lookup(Reinforcements[i].name, 1)) != -1 ) {
1589  Assert ( Wings[wingnum].arrival_cue >= 0 );
1590  if ( Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_FALSE
1591  || Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_KNOWN_FALSE ){
1592  continue;
1593  }
1594  } else {
1595  p_object *p_objp;
1596 
1597  p_objp = mission_parse_get_arrival_ship( Reinforcements[i].name );
1598  if ( p_objp != NULL ) {
1599  if ( Sexp_nodes[p_objp->arrival_cue].value == SEXP_FALSE
1600  || Sexp_nodes[p_objp->arrival_cue].value == SEXP_KNOWN_FALSE ){
1601  continue;
1602  }
1603  } else {
1604  Int3(); // allender says bogus! reinforcement should be here since it wasn't a wing!
1605  continue;
1606  }
1607  }
1608  count++;
1609  }
1610 
1611  return count;
1612 }
1613 
1614 // function to put up window in upper right to allow for player to select the type
1615 // of entity to select for a message (i.e. a wing or a ship)
1617 {
1618  int k, i;
1619 
1620  First_menu_item = 0;
1621 
1622  // Add the items
1623  for (i = 0; i < NUM_COMM_ORDER_TYPES; i++)
1624  {
1625  strcpy_s(MsgItems[i].text, Comm_order_types[i]);
1626  MsgItems[i].active = 1; // assume active
1627  }
1629 
1630 
1631  // check to see if the player is a traitor. If so, then he will not
1632  // be able to do anything from this menu
1633  if ((Player_ship != NULL) && (Player_ship->team == Iff_traitor)) {
1634  for (i = 0; i < MAX_MENU_ITEMS; i++ )
1635  MsgItems[i].active = 0;
1636  goto do_main_menu;
1637  }
1638 
1639  // based on ship counts, wing counts, shortcut active, grey out possible menu choices
1640  if ( !hud_squadmsg_count_ships(0) )
1641  MsgItems[TYPE_SHIP_ITEM].active = 0;
1642 
1643  if ( !hud_squadmsg_count_wings(0) )
1644  MsgItems[TYPE_WING_ITEM].active = 0;
1645 
1646  // check to be sure that we have some fighters/bombers on the players team that we
1647  // can message
1648  if ( !hud_squadmsg_exist_fighters() ){
1649  MsgItems[TYPE_ALL_FIGHTERS_ITEM].active = 0;
1650  }
1651 
1653  MsgItems[TYPE_REINFORCEMENT_ITEM].active = 0;
1654  }
1655 
1656  MsgItems[TYPE_REPAIR_REARM_ITEM].active = 1; // this item will always be available (I think)
1657  MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = 0;
1658 
1659  // AL: 10/13/97
1660  // If the player ship communications are severely damaged, then the player
1661  // will only be able to call for repair/rearm ships
1662  //
1663  // also, only allow support ship if this player is not allowed to messaage.
1665  for ( i = 0; i < MAX_MENU_ITEMS; i++ ){
1666  MsgItems[i].active = 0;
1667  }
1668 
1669  MsgItems[TYPE_REPAIR_REARM_ITEM].active = 1;
1670  }
1671 
1672  // check to see if the player is awaiting repair or being repaired. Active the abort and inactive the repair items
1673  // check to see if the player is scheduled to be repaired by incoming ship
1675  MsgItems[TYPE_REPAIR_REARM_ITEM].active = 0;
1676  MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = 1;
1677  }
1679  MsgItems[TYPE_REPAIR_REARM_ITEM].active = 0;
1680  MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = 1;
1681  }
1682  // if no support available, can't call one in
1683  else if ( !is_support_allowed(Player_obj) ) {
1684  MsgItems[TYPE_REPAIR_REARM_ITEM].active = 0;
1685  MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = 0;
1686  }
1687 
1688  // de-activate the rearm/repair item if the player has a full load of missiles and
1689  // all subsystems at full strength. We will only check if this item hasn't been marked
1690  // inactive because of some other reason
1691  if ( MsgItems[TYPE_REPAIR_REARM_ITEM].active ) {
1692 
1694  MsgItems[TYPE_REPAIR_REARM_ITEM].active = 0;
1695  }
1696  }
1697 
1698  // if using keyboard shortcut, these items are always inactive
1699  if ( Msg_shortcut_command != -1 ) {
1700  MsgItems[TYPE_REPAIR_REARM_ITEM].active = 0;
1701  MsgItems[TYPE_REINFORCEMENT_ITEM].active = 0;
1702  MsgItems[TYPE_REPAIR_REARM_ABORT_ITEM].active = 0;
1703  }
1704 
1705 do_main_menu:
1706  strcpy_s(Squad_msg_title, XSTR( "Message What", 316));
1707  k = hud_squadmsg_get_key();
1708  if ( k != -1 ) { // when k != -1, we have a key that associates with menu item
1709  Assert ( k < Num_menu_items );
1710  if ( k == TYPE_SHIP_ITEM ){
1712  } else if ( k == TYPE_WING_ITEM ) {
1714  } else if ( k == TYPE_ALL_FIGHTERS_ITEM ) {
1716  }
1717 
1718  if ( Msg_shortcut_command == -1 ) {
1719  if ( k == TYPE_REINFORCEMENT_ITEM ) {
1722  } else if ( k == TYPE_REPAIR_REARM_ITEM ){
1724  } else if ( k == TYPE_REPAIR_REARM_ABORT_ITEM ) {
1726  }
1727  }
1728  }
1729 }
1730 
1731 // function to display a list of ships to send a command to
1733 {
1734  int k;
1735 
1736  if ( Num_menu_items == -1 ) {
1737  Num_menu_items = 0;
1739  }
1740 
1741  strcpy_s(Squad_msg_title, XSTR( "Select Ship", 317));
1742  k = hud_squadmsg_get_key();
1743  if ( k != -1 ) { // if true, we have selected a ship.
1744  if ( Msg_shortcut_command == -1 ) {
1745  Msg_instance = MsgItems[First_menu_item + k].instance; // store the instance id in a global
1746  hud_squadmsg_do_mode( SM_MODE_SHIP_COMMAND ); // and move to a new mode
1747  } else {
1748  // we must convert the Msg_shortcut_command value to a value that the message
1749  // system normally uses to select a command. Since the menu
1750  //Assert( Msg_shortcut_command != IGNORE_TARGET_ITEM );
1753  }
1754  }
1755 
1756 }
1757 
1758 // function to display a list of wings to send a command to
1760 {
1761  int k;
1762 
1763  if ( Num_menu_items == -1 ) {
1764  Num_menu_items = 0;
1766  }
1767 
1768  strcpy_s(Squad_msg_title, XSTR( "Select Wing", 318));
1769  k = hud_squadmsg_get_key();
1770  if ( k != -1 ) { // if true, we have selected a ship.
1771  if ( Msg_shortcut_command == -1 ) { // do normal menu stuff when no hoykey active
1772  Msg_instance = MsgItems[First_menu_item + k].instance; // store the instance id in a global
1773  hud_squadmsg_do_mode( SM_MODE_WING_COMMAND ); // and move to a new mode
1774  } else {
1775  //Assert( Msg_shortcut_command != IGNORE_TARGET_ITEM );
1778  }
1779  }
1780 
1781 }
1782 
1783 // code which gives an order to all fighters/bombers. If there is a message shortcut active, then
1784 // make that order apply to all fighters/bombers. Otherwise, move to the ship_command menu
1786 {
1787  if ( Msg_shortcut_command == -1 ) {
1790  } else {
1793  }
1794 }
1795 
1796 // called to actually bring in a reinforcement. For single player games, always gets called.
1797 // for multiplayer games, always called on the server side. Clients should never get here
1798 void hud_squadmsg_call_reinforcement(int reinforcement_num, int player_num)
1799 {
1800  int i, delay;
1801  reinforcements *rp;
1802  p_object *p_objp;
1803 
1804  rp = &Reinforcements[reinforcement_num];
1805 
1806  // safety net mainly for multiplayer servers in case some odd data desync occurs between
1807  // server and clients
1808  if ( MULTIPLAYER_MASTER && (rp->num_uses == rp->uses) ) {
1809  return;
1810  }
1811 
1812  // check to see if the reinforcement called was a wing.
1813  for (i = 0; i < Num_wings; i++ ) {
1814  if ( !stricmp(rp->name, Wings[i].name) ) {
1815  // found a wingname. Call the parse function to create all the ships in this wing
1816  // we must set the arrival cue of the wing to true, otherwise, this won't work!!
1819 
1820  // set up the arrival delay. If it is 0, then make is some random number of seconds
1821  delay = rp->arrival_delay;
1822  if ( delay == 0 )
1823  delay = (int)(frand() * 3.0) + 3;
1824  Wings[i].arrival_delay = timestamp(delay * 1000);
1825  break;
1826  }
1827  }
1828 
1829  // if we found no wing name that matched the reinforcement name, then look for a ship
1830  // of the same name
1831  if ( i == Num_wings ) {
1832  p_objp = mission_parse_get_arrival_ship( rp->name );
1833  if ( p_objp ) {
1834  // by resetting the reinforcement flag, we will allow code which normally handles arrivals
1835  // to make this reinforcement arrive. Doing so keeps the data structures clean.
1836  p_objp->flags &= ~P_SF_REINFORCEMENT;
1837 
1838  // set up the arrival delay
1839  delay = rp->arrival_delay;
1840  if ( delay == 0 )
1841  delay = (int)(frand() * 3.0) + 3; // between 3 and 6 seconds to arrive
1842  p_objp->arrival_delay = timestamp(delay * 1000);
1843  } else {
1844  Int3(); // get allender -- I don't think that this can happen!!!!
1845  return;
1846  }
1847  }
1848 
1849  // increment the number of times this is used. Incremented here on single player and multiplayer
1850  // server side only. Clients keep track of own count when they actually call something in.
1851  rp->num_uses++;
1852 
1853  // commented out on 9/9/98 because these messages simply are not used
1854  /*
1855  // now play a message (if there is one to play) for this reinforcement arrival. The first for loop
1856  // determine how many messages there are to play, since the array is packet. Then, if >= 1 message
1857  // to play, play one
1858  for (i = 0; i < MAX_REINFORCEMENT_MESSAGES; i++ )
1859  if ( !strlen(rp->yes_messages[i]) )
1860  break;
1861 
1862  //if ( i > 0 )
1863  // message_send_to_player( rp->yes_messages[myrand() % i], rp->name, MESSAGE_PRIORITY_NORMAL, HUD_SOURCE_FRIENDLY );
1864  */
1865 
1867 }
1868 
1869 // function to display a list of reinforcements available to the player
1871 {
1872  int i, k, wingnum;
1873  reinforcements *rp;
1874 
1875  if ( Num_menu_items == -1 ) {
1876  Num_menu_items = 0;
1877  for (i = 0; i < Num_reinforcements; i++) {
1878  rp = &Reinforcements[i];
1879 
1880  // don't put reinforcements onto the list that have already been used up.
1881  if ( rp->num_uses == rp->uses ){
1882  continue;
1883  }
1884 
1885  // don't put items which are not on my team
1886  if((Player_ship != NULL) && (ship_get_reinforcement_team(i) != Player_ship->team)){
1887  continue;
1888  }
1889 
1890  // check the arrival cue sexpression of the ship/wing of this reinforcement.
1891  // Goober5000 - if it can't arrive, it doesn't count. This should check
1892  // for SEXP_FALSE as well as SEXP_KNOWN_FALSE, otherwise you end up with
1893  // a reinforcement menu containing no valid selections.
1894  if ( (wingnum = wing_name_lookup(rp->name, 1)) != -1 ) {
1895  Assert ( Wings[wingnum].arrival_cue >= 0 );
1896  if ( Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_FALSE
1897  || Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_KNOWN_FALSE ){
1898  continue;
1899  }
1900  } else {
1901  p_object *p_objp;
1902 
1903  p_objp = mission_parse_get_arrival_ship( rp->name );
1904  if ( p_objp != NULL ) {
1905  if ( Sexp_nodes[p_objp->arrival_cue].value == SEXP_FALSE
1906  || Sexp_nodes[p_objp->arrival_cue].value == SEXP_KNOWN_FALSE ){
1907  continue;
1908  }
1909  } else {
1910  Int3(); // allender says bogus! reinforcement should be here since it wasn't a wing!
1911  continue;
1912  }
1913  }
1914 
1916  strcpy_s( MsgItems[Num_menu_items].text, rp->name );
1918  MsgItems[Num_menu_items].instance = i;
1919  MsgItems[Num_menu_items].active = 0;
1920 
1921  if ( rp->flags & RF_IS_AVAILABLE ) {
1922  MsgItems[Num_menu_items].active = 1;
1923  }
1924 
1925  Num_menu_items++;
1926  }
1927  }
1928 
1929 // hud_squadmsg_display_menu( "Select Reinforcement" );
1930  strcpy_s(Squad_msg_title, XSTR( "Select Ship/Wing", 319)); // AL 11-14-97: Reinforcement didn't fit, so using this for now
1931  k = hud_squadmsg_get_key();
1932  if (k != -1) {
1933  int rnum;
1934 
1935  hud_squadmsg_toggle(); // take us out of message mode
1936 
1937  rnum = MsgItems[First_menu_item + k].instance;
1938 
1939  // check to see if trying to call a reinforcement not yet available. If so, maybe play message, but
1940  // definately bail
1941  if ( MsgItems[First_menu_item + k].active == 0 ) {
1942  return;
1943  }
1944 
1945  // in single player, or a multiplayer master, call in the reinforcement. Clients send a packet to the
1946  // server
1947  if ( MULTIPLAYER_CLIENT ) {
1948  Reinforcements[rnum].num_uses++; // increment this variable here since clients need to maintain a valid count
1950  } else {
1952  }
1953  }
1954 }
1955 
1956 // function to display list of commands for a ship
1957 
1959 {
1960  int k;
1961  int i, orders, default_orders;
1962 
1963  // when adding ship commands, we must look at the type of ship, and what messages that
1964  // ship allows. First, place all messages that are possible onto the menu, then
1965 
1966  // see if messaging all ships or just one. Messaging all ships will mean all default orders
1967  // show on comm menu.
1970  default_orders = ship_get_default_orders_accepted( &Ship_info[Ships[Msg_instance].ship_info_index] );
1971  } else {
1972 
1973  default_orders = DEFAULT_MESSAGES;
1974  orders = default_orders;
1975  }
1976 
1977  First_menu_item = 0;
1978  Num_menu_items = 0;
1979  for ( i = 0; i < NUM_COMM_ORDER_ITEMS; i++ ) {
1980  // check to see if the comm order should even be added to the menu -- if so, then add it
1981  // the order will be activated if the bit is set for the ship.
1982  if ( default_orders & Comm_orders[i].item ) {
1984  strcpy_s(MsgItems[Num_menu_items].text, Comm_orders[i].name);
1985  MsgItems[Num_menu_items].instance = Comm_orders[i].item;
1986  MsgItems[Num_menu_items].active = 0;
1987  // check the bit to see if the command is active
1988  if ( orders & Comm_orders[i].item )
1989  MsgItems[Num_menu_items].active = 1;
1990 
1991  // if the order cannot be carried out by the ship, then item should be inactive
1992  if ( (Msg_instance != MESSAGE_ALL_FIGHTERS) && !hud_squadmsg_ship_order_valid( Msg_instance, Comm_orders[i].item ) )
1993  MsgItems[Num_menu_items].active = 0;
1994 
1995  // do some other checks to possibly gray out other items.
1996  // if no target, remove any items which are associated with the players target
1998  MsgItems[Num_menu_items].active = 0;
1999 
2000  // if messaging all fighters, see if we should gray out the order if no one will accept it,
2001  // or modify the text if only some of the ships will accept it
2003  ship_obj *so;
2004  ship *shipp;
2005  int partial_accept, all_accept; // value which tells us what to do with menu item
2006 
2007  all_accept = Comm_orders[i].item;
2008  partial_accept = 0;
2009  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
2010 
2011  // don't send messge to ships not on player's team, or that are in a wing.
2012  shipp = &Ships[Objects[so->objnum].instance];
2013  if ( shipp->team != Player_ship->team )
2014  continue;
2015 
2016  // don't send message to non fighter wings
2017  if ( !(Ship_info[shipp->ship_info_index].flags & (SIF_FIGHTER | SIF_BOMBER)) )
2018  continue;
2019 
2020  all_accept &= shipp->orders_accepted; // 'and'ing will either keep this bit set or zero it properly
2021  partial_accept |= (shipp->orders_accepted & Comm_orders[i].item); // 'or'ing will tell us if at least one accepts
2022  }
2023 
2024  if ( !all_accept ) {
2025  // either modify the text if a partial accept, or grey it out if no one accepts
2026  if ( partial_accept ) {
2027  strcat_s( MsgItems[Num_menu_items].text, XSTR( "(*)", 320) );
2028  } else {
2029  MsgItems[Num_menu_items].active = 0;
2030  }
2031  }
2032  }
2033 
2034  Num_menu_items++;
2035  }
2036  }
2037 
2038  strcpy_s( Squad_msg_title, XSTR( "What Command", 321) );
2039  k = hud_squadmsg_get_key();
2040 
2041  // when we get a valid goal, we must add the goal to the ai ship's goal list
2042 
2043  if ( k != -1 ) {
2044  Assert ( k < Num_menu_items );
2045  // when messaging all fighters or ignoring target, call the send_to_all_fighters routine
2046  // Goober5000 - ignore no longer sends to all fighters
2048  hud_squadmsg_send_to_all_fighters(MsgItems[k].instance);
2049  else
2051 
2053  }
2054 }
2055 
2056 // function to display list of command for a wing
2058 {
2059  int k;
2060  wing *wingp;
2061  int default_orders, i, orders, shipnum;
2062 
2063  // when adding commands for wings, we will look at all of the ships in the wing, and create
2064  // the order list from that set of ships. In the future, we may want to do something else....
2065 
2066  wingp = &Wings[Msg_instance];
2067 
2068  // or together all of the orders for all the ships in the wing
2069  default_orders = 0;
2070  for ( i = 0; i < wingp->current_count; i++ ) {
2072  default_orders |= orders;
2073  }
2074  default_orders &= ~CAPTURE_TARGET_ITEM; // we cannot capture any target with a wing.
2075 
2076  Num_menu_items = 0;
2077  shipnum = wingp->ship_index[wingp->special_ship];
2078  Assertion(shipnum >= 0, "Special ship (%d) for wing '%s' has a negative ship_index (%d). This should not happen; get a coder!\n", wingp->special_ship, wingp->name, shipnum);
2079  orders = Ships[shipnum].orders_accepted; // get the orders that the wing leader will accept
2080  for ( i = 0; i < NUM_COMM_ORDER_ITEMS; i++ ) {
2081  // add the set of default orders to the comm menu. We will currently allow all messages
2082  // to be available in the wing.
2083  if ( default_orders & Comm_orders[i].item ) {
2085  strcpy_s(MsgItems[Num_menu_items].text, Comm_orders[i].name);
2086  MsgItems[Num_menu_items].instance = Comm_orders[i].item;
2087  MsgItems[Num_menu_items].active = 0;
2088 
2089  // possibly grey out the menu item depending on whether or not the "wing" will accept this order
2090  // the "wing" won't accept the order if the first ship in the wing doesn't accept it.
2091  if ( orders & Comm_orders[i].item )
2092  MsgItems[Num_menu_items].active = 1;
2093 
2094  // do some other checks to possibly gray out other items.
2095  // if no target, remove any items which are associated with the players target
2097  MsgItems[Num_menu_items].active = 0;
2098 
2099  Num_menu_items++;
2100  }
2101  }
2102 
2103 
2104  strcpy_s(Squad_msg_title, XSTR( "What Command", 321) );
2105  k = hud_squadmsg_get_key();
2106  if ( k != -1 ) {
2107 
2108  // ignore target gets sent to everyone.
2109  /* Goober5000 - not anymore
2110  if (MsgItems[k].instance == IGNORE_TARGET_ITEM)
2111  hud_squadmsg_send_to_all_fighters(MsgItems[k].instance);
2112  else */
2113  hud_squadmsg_send_wing_command(Msg_instance, MsgItems[k].instance, 1);
2114 
2116  }
2117 }
2118 
2119 
2120 
2121 //----------------------------------------------------------
2122 // external entry points below!!!!
2123 
2124 // when starting messaging mode, we must remove old bindings from the
2125 // keys that are used for messaging mode (which will get restored when
2126 // messaging mode is done).
2127 
2128 // this code below will get called only the key config changes (from ControlsConfig.cpp)
2129 // or if the bindings haven't been saved yet. This code doesn't remove the bindings
2130 // but just sets up the array so that the bindings can be removed when messaging
2131 // mode is entered.
2132 //
2133 // do_scroll indicates whether we should save the page up and page down keys
2134 void hud_squadmsg_save_keys( int do_scroll )
2135 {
2136 // int i, j;
2137 
2138  num_keys_saved = 0;
2139 
2140 /*
2141  for ( j=0; j<MAX_KEYS_USED; j++ ) {
2142  for ( i=0; Control_config[i].text[0]; i++ ) { // the text field in this structure is empty at the end of the config list
2143  if ( Control_config[i].key_id == keys_used[j] ) { // this is true if we have a match
2144 
2145  // if we are not saving scrolling keys and we are trying to match page up and page down
2146  // then skip them.
2147  if ( !do_scroll && ((keys_used[j] == KEY_PAGEDOWN) || (keys_used[j] == KEY_PAGEUP)) )
2148  continue;
2149 
2150  Assert( num_keys_saved < MAX_KEYS_USED );
2151  key_save[num_keys_saved].option_num = i;
2152  key_save[num_keys_saved].key_value = keys_used[j];
2153  num_keys_saved++;
2154  break; // done with this key -- move to next.
2155  }
2156  }
2157  }
2158 */
2159 }
2160 
2161 // function is called once per mission start. Initializes those values
2162 // which only need to be inited once per mission.
2163 void hud_init_squadmsg( void )
2164 {
2166  Squadmsg_history.clear();
2167 }
2168 
2169 // external entry point into code which changes the messaging mode based on the
2170 // previous player flag value. I thought it better to isolate all system changes
2171 // in this code.
2173 {
2174  // if the emp effect is active, always ignore this
2175  if(emp_active_local()){
2176  return;
2177  }
2178 
2179  // if entering this mode, must setup messaging system. Don't start squadmessging if
2180  // the player is dead.
2181  if ( !(Player->flags & PLAYER_FLAGS_MSG_MODE) ) {
2182  if ( Game_mode & GM_DEAD ){
2183  return;
2184  }
2185 
2187  return;
2188  }
2189 
2191  } else {
2192  hud_squadmsg_end();
2193  }
2194 
2196 }
2197 
2198 // extern entry point to allow messaging of enemies
2200 {
2202  // if we just entered message mode, turn on var that says to message enemies
2204  Msg_enemies = 1;
2205 }
2206 
2207 // external entry point into code when a keyboard shortcut is used for a command
2208 // we are passed in an ID for the command to set internal variables. This command
2209 // will be used in place of the last menu in the messaging code
2210 void hud_squadmsg_shortcut( int command )
2211 {
2212  // check if the communications system is capable of sending a message
2213  if ( (hud_communications_state(Player_ship) != COMM_OK) && (command != REARM_REPAIR_ME_ITEM) ) {
2214  HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Messaging is restricted due to communications damage", 331));
2215  return;
2216  }
2217 
2218  // observers in multiplayer games cannot have this active either
2220  return;
2221 
2222  // in multiplayer and I cannot message, don't allow anything except calling in for rearm
2223  if ( (Game_mode & GM_MULTIPLAYER) && !multi_can_message(Net_player) && (command != REARM_REPAIR_ME_ITEM) )
2225 
2226  // player ships which turn traitor cannot rearm
2227  if ( Player_ship->team == Iff_traitor )
2228  return;
2229 
2230  if ( Player->flags & PLAYER_FLAGS_MSG_MODE ) // we are already in messaging mode -- maybe do sometime more interesting?
2231  return;
2233  Msg_shortcut_command = command; // save the command for later use
2234 
2235  if (Msg_shortcut_command == CAPTURE_TARGET_ITEM) // some commands only apply to wings or ships
2236  Squad_msg_mode = SM_MODE_SHIP_SELECT; // -- don't offer choice
2237 
2238  /* Goober5000 - again with the stupid logic
2239  else if ( Msg_shortcut_command == IGNORE_TARGET_ITEM ) { // ignoring target applied to all ships
2240  hud_squadmsg_toggle(); // turns off mode which was turned on above
2241  hud_squadmsg_send_to_all_fighters( Msg_shortcut_command );
2242  }
2243  */
2244 }
2245 
2246 // external entry point which is called when the player hits a selection key (1-0) while in messaging
2247 // mode. If we are in messaging mode, send the shortcut command to the ships that are part of the
2248 // passed in selection set. If there is no shortcut command, do nothing. Returns 1 if the key
2249 // was used, else 0. This return value is used to tell the key control system that it should
2250 // call the normal targeting selection stuff.
2252 {
2253  htarget_list *hitem, *plist;
2254  int send_message;
2255  object *objp;
2256 
2258 
2259  if ( Msg_shortcut_command == -1 )
2260  return 0;
2261 
2262  Assert ( (k >= 0) && (k < MAX_KEYED_TARGETS) );
2263  plist = &(Player->keyed_targets[k]);
2264 
2265  if ( EMPTY(plist) ) // be sure that we have at least one ship in the list
2266  return 0;
2267 
2268  send_message = 1;
2269  // for each ship in the selection set list, send the shortcut command that the player
2270  // previously entered. Be sure to check that we are not trying to send a command to
2271  // an enemy ship.
2272  for ( hitem = GET_FIRST(plist); hitem != END_OF_LIST(plist); hitem = GET_NEXT(hitem) ) {
2273  objp = hitem->objp;
2274  Assert ( objp->type == OBJ_SHIP );
2275  if ( Ships[objp->instance].team != Player_ship->team )
2276  continue;
2277 
2278  // be sure that this ship can accept this command
2280  continue;
2281 
2282  hud_squadmsg_send_ship_command( objp->instance, Msg_shortcut_command, send_message, SQUADMSG_HISTORY_ADD_ENTRY );
2283  send_message = 0;
2284  }
2285 
2286  hud_squadmsg_toggle(); // turn off messaging mode
2287  return 1;
2288 }
2289 
2290 
2291 // the next function is called once a frame when the player is messaging someone
2292 // in his squad. After a period of 5 seconds of inactivity (i.e. no keypress to
2293 // select something in the menu), the menu will disappear. This function will only
2294 // get called if the player flag PLAYER_FLAG_MSG_MODE is set. Parameter is the key
2295 // that was hit this frame
2296 
2298 {
2299  int target_changed;
2300 
2301  Assert ( Player->flags & PLAYER_FLAGS_MSG_MODE ); // be sure that messaging mode is set!!!
2302 
2303  // if the player is now dead, or the timestamp elapsed, then get out of messaging mode.
2306  return 0;
2307  }
2308 
2309  Msg_key_used = 0;
2310 
2311  // check the player's current target. Change in target resets the timer
2312  target_changed = 0;
2315  target_changed = 1;
2316  }
2317 
2320  target_changed = 1;
2321  }
2322 
2323  // check for multiplayer mode - this is really a special case checker for support ship requesting and aborting
2325  // send the correct packet
2328  else
2330 
2331  // make sure to toggle the mode off
2333 
2334  return 1;
2335  }
2336 
2337  switch( Squad_msg_mode ) {
2338 
2339  case SM_MODE_TYPE_SELECT:
2341  break;
2342 
2343  case SM_MODE_SHIP_SELECT:
2345  break;
2346 
2347  case SM_MODE_WING_SELECT:
2349  break;
2350 
2351  case SM_MODE_SHIP_COMMAND:
2353  break;
2354 
2355  case SM_MODE_WING_COMMAND:
2357  break;
2358 
2361  break;
2362 
2363  case SM_MODE_REPAIR_REARM:
2364  hud_squadmsg_repair_rearm(1); // note we return right away. repair/rearm code handles messaging, etc
2365  break;
2366 
2368  hud_squadmsg_repair_rearm_abort(1); // note we return right away. repair/rearm code handles messaging, etc
2369  break;
2370 
2371  case SM_MODE_ALL_FIGHTERS:
2373  break;
2374 
2375  default:
2376  Int3(); // get allender -- invalid mode in messaging system
2377  break;
2378 
2379  }
2380 
2381  // be sure to reset the clip region
2382  HUD_reset_clip(); // JAS: Is this needed?
2383 
2384  if ( Msg_key_used || target_changed ) {
2386  return 1;
2387  } else
2388  return 0;
2389 }
2390 
2392 {
2393  squadmsg_history *latest_order = new squadmsg_history();
2394 
2395  if (!strcmp(name, "All Fighters")) {
2396  latest_order->order_to = -1;
2397  }
2398  else {
2399  latest_order->order_to = get_parse_name_index(name);
2400  }
2401  latest_order->order = order;
2402  latest_order->order_time = Missiontime;
2403 
2404  //stick it in history
2405  Squadmsg_history.push_back(*latest_order);
2406  delete latest_order;
2407 }
2408 
2409 void hud_update_last_order(char *target, int order_source, int special_index)
2410 {
2411  squadmsg_history *latest_order = &Squadmsg_history.back();
2412  if (target) {
2413  latest_order->target = get_parse_name_index(target);
2414  }
2415  if (MULTIPLAYER_MASTER && order_source != -1) {
2416  latest_order->order_from = Objects[Net_players[order_source].m_player->objnum].instance;
2417  }
2418  else if (order_source == -1) {
2419  latest_order->order_from = Player_obj->instance;
2420  }
2421 
2422  latest_order->special_index = special_index;
2423 }
2424 
2425 int hud_query_order_issued(char *to, char *order_name, char *target_name, int timestamp, char *from, char *special_argument)
2426 {
2427  int i, order = -1, ship_or_wing = -1, target = -1, source = -1;
2428 
2429  // if the desired order was not sent to all fighters
2430  if (strcmp(to, "<all fighters>")) {
2431  ship_or_wing = get_parse_name_index(to);
2432  }
2433 
2434  // get the target ship
2435  if (target_name != NULL) {
2436  target = get_parse_name_index(target_name);
2437  }
2438 
2439  if (MULTIPLAYER_MASTER && (from != NULL)) {
2440  source = ship_name_lookup(from, 1);
2441  }
2442 
2443 
2444  for (i = 0; i < NUM_COMM_ORDER_ITEMS; i++)
2445  if (!stricmp(order_name, Comm_orders[i].name))
2446  order = Comm_orders[i].item;
2447 
2448  // Goober5000 - if not found, check compatibility
2449  if (order == -1)
2450  {
2451  if (!stricmp(order_name, "Attack my target"))
2452  {
2453  i = 0; // it maps to option 0, "Destroy my target"
2454  order = Comm_orders[i].item;
2455  }
2456  }
2457 
2458  Assert(order != -1);
2459  for (i = 0; i < (int)Squadmsg_history.size(); i++) {
2460  if (Squadmsg_history[i].order == order) {
2461  if (ship_or_wing == Squadmsg_history[i].order_to) {
2462  if (target == -1 || Squadmsg_history[i].target == target) {
2463  if ((!timestamp) || (Squadmsg_history[i].order_time + i2f(timestamp) >= Missiontime) ) {
2464  // In multiplayer games we may wish to check who sent the order
2465  if (MULTIPLAYER_MASTER) {
2466  if ((source != -1) && (Squadmsg_history[i].order_from != source)) {
2467  continue;
2468  }
2469  }
2470 
2471  // some orders will have additional arguments
2472  if (order & DISABLE_SUBSYSTEM_ITEM) {
2473  if (special_argument == NULL) {
2474  continue;
2475  }
2476 
2477  int target_ship = ship_name_lookup(target_name);
2478 
2479  if(target_ship<0) {
2480  continue;
2481  }
2482 
2483  int subsys_index = ship_get_subsys_index(&Ships[target_ship], special_argument, 1);
2484  // if the order is for s different subsystem
2485  if (Squadmsg_history[i].special_index != subsys_index) {
2486  continue;
2487  }
2488  }
2489 
2490  // if we make it this far then the orders match
2491  return 1;
2492  }
2493  }
2494  }
2495  }
2496  }
2497 
2498  return 0;
2499 }
2500 
2503 {
2504 }
2505 
2507 {
2508  flash_timer[0] = timestamp(1);
2509  flash_timer[1] = timestamp(1);
2510  flash_flag = false;
2511 
2513 }
2514 
2516 {
2517  Header_offsets[0] = x;
2518  Header_offsets[1] = y;
2519 }
2520 
2522 {
2523  Item_start_offsets[0] = x;
2524  Item_start_offsets[1] = y;
2525 }
2526 
2528 {
2530 }
2531 
2533 {
2535 }
2536 
2538 {
2539  Item_h = h;
2540 }
2541 
2543 {
2544  Item_offset_x = x;
2545 }
2546 
2548 {
2549  Pgup_offsets[0] = x;
2550  Pgup_offsets[1] = y;
2551 }
2552 
2554 {
2555  Pgdn_offsets[0] = x;
2556  Pgdn_offsets[1] = y;
2557 }
2558 
2559 void HudGaugeSquadMessage::initBitmaps(char *fname_top, char *fname_middle, char *fname_bottom)
2560 {
2561  Mbox_gauge[0].first_frame = bm_load_animation(fname_top, &Mbox_gauge[0].num_frames);
2562  if ( Mbox_gauge[0].first_frame == -1 ) {
2563  Warning(LOCATION, "Could not load in ani: %s\n", fname_top);
2564  }
2565 
2566  Mbox_gauge[1].first_frame = bm_load_animation(fname_middle, &Mbox_gauge[1].num_frames);
2567  if ( Mbox_gauge[1].first_frame == -1 ) {
2568  Warning(LOCATION, "Could not load in ani: %s\n", fname_middle);
2569  }
2570 
2571  Mbox_gauge[2].first_frame = bm_load_animation(fname_bottom, &Mbox_gauge[2].num_frames);
2572  if ( Mbox_gauge[2].first_frame == -1 ) {
2573  Warning(LOCATION, "Could not load in ani: %s\n", fname_bottom);
2574  }
2575 }
2576 
2578 {
2579  flash_timer[0] = timestamp(duration);
2580 }
2581 
2583 {
2584  bool draw_bright = false;
2585 
2586  if(!timestamp_elapsed(flash_timer[0])) {
2587  if(timestamp_elapsed(flash_timer[1])) {
2588  if(flash_fast) {
2590  } else {
2592  }
2594  }
2595 
2596  if(flash_flag) {
2597  draw_bright = true;
2598  }
2599  }
2600 
2601  return draw_bright;
2602 }
2603 
2605 {
2607  return false;
2608  }
2609 
2610  if (hud_disabled()) {
2611  return false;
2612  }
2613 
2614  if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
2615  return false;
2616  }
2617 
2618  if ((Viewer_mode & disabled_views)) {
2619  return false;
2620  }
2621 
2622  if (!( Player->flags & PLAYER_FLAGS_MSG_MODE )) {
2623  return false;
2624  }
2625 
2626  return true;
2627 }
2628 
2629 void HudGaugeSquadMessage::render(float frametime)
2630 {
2631  char *title;
2632  int bx, by, sx, sy, i, nitems, none_valid, messaging_allowed;
2633 
2634  title = Squad_msg_title;
2635 
2636  // setup color/font info
2637  // hud_set_default_color();
2638  setGaugeColor();
2639 
2640  // draw top of frame
2641  if ( Mbox_gauge[0].first_frame >= 0 ) {
2642  renderBitmap(Mbox_gauge[0].first_frame, position[0], position[1]);
2643  }
2644 
2645  // hud_set_bright_color();
2647  if ( title ) {
2648  renderString(position[0] + Header_offsets[0], position[1] + Header_offsets[1], title);
2649  }
2650 
2652  nitems = Num_menu_items;
2653  else {
2654  if ( First_menu_item == 0 ) // First_menu_item == 0 means first page of items
2655  nitems = MAX_MENU_DISPLAY;
2656  else if ( (Num_menu_items - First_menu_item) <= MAX_MENU_DISPLAY ) // check if remaining items fit on one page
2657  nitems = Num_menu_items - First_menu_item;
2658  else {
2659  nitems = MAX_MENU_DISPLAY;
2660  }
2661  }
2662 
2663  sx = position[0] + Item_start_offsets[0];
2664  sy = position[1] + Item_start_offsets[1];
2665  bx = position[0]; // global x-offset where bitmap gets drawn
2666  by = position[1] + Middle_frame_start_offset_y; // global y-offset where bitmap gets drawn
2667 
2668  none_valid = 1; // variable to tell us whether all items in the menu are valid or not
2669 
2670  // use another variable to tell us whether we can message or not.
2671  messaging_allowed = 1;
2672 
2674  messaging_allowed = 0;
2675  }
2676 
2677  for ( i = 0; i < nitems; i++ ) {
2678  int item_num;
2679  char *text = MsgItems[First_menu_item+i].text;
2680 
2681  // blit the background
2682  // hud_set_default_color();
2683  setGaugeColor();
2684  if ( Mbox_gauge[1].first_frame >= 0 ) {
2685  renderBitmap(Mbox_gauge[1].first_frame, bx, by);
2686  }
2687  by += Item_h;
2688 
2689  // set the text color
2690  if ( MsgItems[First_menu_item+i].active ) {
2691  // hud_set_bright_color();
2693  } else {
2694  /*
2695  dim_index = MIN(5, HUD_color_alpha - 2);
2696  if ( dim_index < 0 ) {
2697  dim_index = 0;
2698  }
2699  gr_set_color_fast(&HUD_color_defaults[dim_index]);
2700  */
2701 
2703  }
2704 
2705  // first do the number
2706  item_num = (i+1) % MAX_MENU_DISPLAY;
2707  renderPrintf(sx, sy, EG_SQ1 + i, NOX("%1d."), item_num);
2708 
2709  // then the text
2710  renderString(sx + Item_offset_x, sy, EG_SQ1 + i, text);
2711 
2712  sy += Item_h;
2713 
2714  // if we have at least one item active, then set the variable so we don't display any
2715  // message about no active items
2716  if ( MsgItems[First_menu_item+i].active )
2717  none_valid = 0;
2718  }
2719 
2720  // maybe draw an extra line in to make room for [pgdn], or for the 'no active items'
2721  // display
2722  if ( !messaging_allowed || none_valid || ((First_menu_item + nitems) < Num_menu_items) || (Msg_shortcut_command != -1) ) {
2723  // blit the background
2724  // hud_set_default_color();
2725  setGaugeColor();
2726  if ( Mbox_gauge[1].first_frame >= 0 ) {
2727  renderBitmap(Mbox_gauge[1].first_frame, bx, by);
2728  }
2729  by += Item_h;
2730  }
2731 
2732  // draw the bottom of the frame
2733  // hud_set_default_color();
2734  setGaugeColor();
2735  if ( Mbox_gauge[2].first_frame >= 0 ) {
2736 
2737  renderBitmap(Mbox_gauge[2].first_frame, bx, by + bottom_bg_offset);
2738  }
2739 
2740  // determine if we should put the text "[more]" at top or bottom to indicate you can page up or down
2743  if ( First_menu_item > 0 ) {
2744  renderPrintf(position[0] + Pgup_offsets[0], position[1] + Pgup_offsets[1], XSTR( "[pgup]", 312) );
2745  }
2746 
2747  if ( (First_menu_item + nitems) < Num_menu_items ) {
2748  renderPrintf(position[0] + Pgdn_offsets[0], position[1] + Pgdn_offsets[1], XSTR( "[pgdn]", 313));
2749  }
2750 
2751  if ( messaging_allowed ) {
2752  if ( none_valid ){
2753  renderPrintf( sx, by - Item_h + 2, XSTR( "No valid items", 314));
2754  } else if (Msg_shortcut_command != -1){
2756  }
2757  } else {
2758  // if this player is not allowed to message, then display message saying so
2759  renderPrintf( sx, by - Item_h + 2, XSTR( "Not allowed to message", 315));
2760  }
2761 
2762 }
2763 
2765 {
2766  for (int i = 0; i < NUM_MBOX_FRAMES; i++ ) {
2767  bm_page_in_aabitmap( Mbox_gauge[i].first_frame, Mbox_gauge[i].num_frames );
2768  }
2769 }
#define KEY_0
Definition: key.h:71
virtual void initialize()
Definition: hud.cpp:1049
char Parse_names[MAX_SHIPS+MAX_WINGS][NAME_LENGTH]
#define MESSAGE_PRIORITY_NORMAL
#define REARM_REPAIR_ME_ITEM
Definition: hudsquadmsg.h:49
#define SHIP_GET_UNSILENCED
Definition: ship.h:1789
#define SQUAD_MSG_REINFORCEMENT
Definition: multi.h:359
int timestamp(int delta_ms)
Definition: timer.cpp:226
bool message_gauge
Definition: hud.h:220
wing Wings[MAX_WINGS]
Definition: ship.cpp:128
#define MULTIPLAYER_CLIENT
Definition: multi.h:132
int i
Definition: multi_pxo.cpp:466
fix Missiontime
Definition: systemvars.cpp:19
#define KEY_6
Definition: key.h:77
#define MESSAGE_REARM_ON_WAY
#define SM_MODE_ALL_FIGHTERS
Definition: hudsquadmsg.h:26
model_subsystem * system_info
Definition: ship.h:314
weapon Weapons[MAX_WEAPONS]
Definition: weapons.cpp:78
int hud_squadmsg_get_total_keys()
ai_info * Player_ai
Definition: ai.cpp:24
int ai_abort_rearm_request(object *requester_objp)
Definition: aicode.cpp:15338
#define LOG_PLAYER_CALLED_FOR_REARM
Definition: missionlog.h:31
int team
Definition: ship.h:606
#define NUM_MBOX_FRAMES
Definition: hudsquadmsg.h:62
int disabled_views
Definition: hud.h:221
void initBitmaps(char *fname_top, char *fname_middle, char *fname_bottom)
void initPgDnOffsets(int x, int y)
#define HUD_C_BRIGHT
Definition: hud.h:162
int num_uses
Definition: ship.h:86
int flags
Definition: player.h:104
void mission_log_add_entry(int type, char *pname, char *sname, int info_index)
Definition: missionlog.cpp:184
int is_instructor(object *objp)
Definition: aicode.cpp:4895
int objnum
Definition: ship.h:537
#define PROTECT_TARGET_ITEM
Definition: hudsquadmsg.h:41
int Game_mode
Definition: systemvars.cpp:24
#define MAX_KEYS_USED
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
#define TARGET_MESSAGES
Definition: hudsquadmsg.h:104
void hud_squadmsg_rearm_shortcut()
#define MSG_KEY_EAT_TIME
Definition: hudsquadmsg.cpp:40
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
#define KEY_PAGEDOWN
Definition: key.h:178
#define KEY_5
Definition: key.h:76
net_player * Net_player
Definition: multi.cpp:94
SCP_vector< game_snd > Snds
Definition: gamesnd.cpp:19
mmode_item MsgItems[MAX_MENU_ITEMS]
int hud_query_order_issued(char *to, char *order_name, char *target_name, int timestamp, char *from, char *special_argument)
object * objp
Definition: hudtarget.h:52
struct key_store key_store
GLsizei const GLfloat * value
Definition: Glext.h:5646
void ai_add_ship_goal_player(int type, int mode, int submode, char *shipname, ai_info *aip)
Definition: aigoals.cpp:757
#define SF2_NO_SUBSPACE_DRIVE
Definition: ship.h:487
#define SM_ATTACK
Definition: ai.h:247
void ai_add_wing_goal_player(int type, int mode, int submode, char *shipname, int wingnum)
Definition: aigoals.cpp:783
#define AI_GOAL_DOCK
Definition: aigoals.h:30
#define KEY_8
Definition: key.h:79
#define VM_WARP_CHASE
Definition: systemvars.h:37
player * m_player
Definition: multi.h:459
#define MAX_SHIPS
Definition: globals.h:37
int flags
Definition: ship.h:88
void setGaugeColor(int bright_index=-4)
Definition: hud.cpp:445
#define AI_GOAL_GUARD
Definition: aigoals.h:38
#define WF_WING_GONE
Definition: ship.h:1501
void hud_squadmsg_call_reinforcement(int reinforcement_num, int player_num)
#define SQUADMSG_HISTORY_ADD_ENTRY
Definition: hudsquadmsg.h:156
int departure_anchor
Definition: ship.h:618
#define NUM_COMM_ORDER_ITEMS
Definition: hudsquadmsg.h:36
LOCAL int Msg_key_used
Definition: hudsquadmsg.cpp:43
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
int target_objnum
Definition: ai.h:339
void hud_init_squadmsg(void)
LOCAL int Msg_mode_timestamp
Definition: hudsquadmsg.cpp:46
#define KEY_1
Definition: key.h:72
#define TYPE_SHIP_ITEM
int departure_location
Definition: ship.h:617
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
int ai_index
Definition: ship.h:538
int hud_squadmsg_send_wing_command(int wingnum, int command, int send_message, int update_history, int player_num)
int Msg_shortcut_command
Definition: hudsquadmsg.cpp:48
general failure sound for any event
Definition: gamesnd.h:297
#define AI_GOAL_STAY_NEAR_SHIP
Definition: aigoals.h:47
#define VM_EXTERNAL
Definition: systemvars.h:31
#define STAY_NEAR_TARGET_ITEM
Definition: hudsquadmsg.h:52
#define AI_GOAL_CHASE_ANY
Definition: aigoals.h:41
#define WF_RESET_REINFORCEMENT
Definition: ship.h:1505
void hud_squadmsg_do_mode(int mode)
CButton * team
#define NETPLAYER_IS_OBSERVER(player)
Definition: multi.h:626
#define STAY_NEAR_ME_ITEM
Definition: hudsquadmsg.h:51
LOCAL int Msg_eat_key_timestamp
Definition: hudsquadmsg.cpp:53
#define MAX_KEYED_TARGETS
Definition: player.h:26
GLclampf f
Definition: Glext.h:7097
#define AI_GOAL_WARP
Definition: aigoals.h:33
#define CAPTURE_TARGET_ITEM
Definition: hudsquadmsg.h:46
#define SHIP_INDEX(shipp)
Definition: ship.h:1602
void hud_squadmsg_type_select()
ai_info Ai_info[MAX_AI_INFO]
Definition: ai.cpp:23
#define Assertion(expr, msg,...)
Definition: clang.h:41
object obj_used_list
Definition: object.cpp:53
#define AI_GOAL_DISARM_SHIP
Definition: aigoals.h:40
#define COVER_ME_ITEM
Definition: hudsquadmsg.h:44
Definition: ship.h:1516
ship_subsys * targeted_subsys
Definition: ai.h:472
GLenum mode
Definition: Glext.h:5794
void initBottomBgOffset(int offset)
char text[NAME_LENGTH]
GLenum GLuint GLenum GLsizei const GLchar * message
Definition: Glext.h:5156
Definition: ai.h:329
uint flags
Definition: ship.h:644
int Menu_pgup_coords[GR_NUM_RESOLUTIONS][2]
Definition: hudsquadmsg.cpp:85
#define EG_SQ1
Definition: emp.h:55
#define KEY_PAGEUP
Definition: key.h:175
#define MESSAGE_ALL_FIGHTERS
Definition: hudsquadmsg.h:29
#define OF_PLAYER_SHIP
Definition: object.h:109
object * objp
Definition: lua.cpp:3105
#define ENEMY_TARGET_MESSAGES
Definition: hudsquadmsg.h:101
#define DEFAULT_MSG_TIMEOUT
Definition: hudsquadmsg.cpp:39
#define Int3()
Definition: pstypes.h:292
#define HUD_OBJECT_SQUAD_MSG
Definition: hudparse.h:106
void HUD_sourced_printf(int source, const char *format,...)
Definition: hudmessage.cpp:571
#define MESSAGE_ENGAGE
#define AI_GOAL_NONE
Definition: ai.h:194
ship * shipp
Definition: lua.cpp:9162
int arrival_delay
Definition: ship.h:1544
ship_subsys_info subsys_info[SUBSYSTEM_MAX]
Definition: ship.h:632
int ai_flags
Definition: ai.h:330
#define SQUAD_MSG_ALL
Definition: multi.h:358
#define TYPE_REPAIR_REARM_ABORT_ITEM
int multi_msg_eval_wing_squadmsg(int wingnum, int command, ai_info *aif, int player_num)
Definition: multi_pmsg.cpp:621
int arrival_delay
Definition: missionparse.h:374
int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *keyframe, int can_drop_frames, int dir_type)
Loads a bitmap sequance so we can draw with it.
Definition: bmpman.cpp:1420
int Mbox_item_h[GR_NUM_RESOLUTIONS]
Definition: hudsquadmsg.cpp:56
Definition: hud.h:201
#define AIG_TYPE_PLAYER_SHIP
Definition: ai.h:99
int weapon_info_index
Definition: weapon.h:164
int hud_support_find_closest(int objnum)
Locate the closest support ship which is trying to dock with player.
Definition: hud.cpp:2655
reinforcements Reinforcements[MAX_REINFORCEMENTS]
Definition: ship.cpp:165
#define MAX_MENU_ITEMS
int objnum
Definition: ship.h:1483
#define SM_MODE_WING_SELECT
Definition: hudsquadmsg.h:20
#define DISARM_TARGET_ITEM
Definition: hudsquadmsg.h:40
void hud_squadmsg_page_down()
int hud_squadmsg_wing_valid(wing *wingp)
#define IGNORE_TARGET_ITEM
Definition: hudsquadmsg.h:42
int key_down_count(int scancode)
Definition: key.cpp:653
#define SIF_BOMBER
Definition: ship.h:886
int orders_accepted
Definition: ship.h:624
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define AIS_DOCK_0
Definition: ai.h:269
int instance
Definition: object.h:150
#define DEPART_AT_DOCK_BAY
Definition: missionparse.h:246
key_store key_save[MAX_KEYS_USED]
#define ATTACK_TARGET_ITEM
Definition: hudsquadmsg.h:38
GLintptr offset
Definition: Glext.h:5497
p_object * mission_parse_get_arrival_ship(const char *name)
Returns the parse object on the ship arrival list associated with the given name. ...
#define VM_DEAD_VIEW
Definition: systemvars.h:33
net_player_info p_info
Definition: multi.h:473
void initItemHeight(int h)
void hud_squadmsg_wing_select()
#define KEY_9
Definition: key.h:80
int ship_get_reinforcement_team(int r_index)
Definition: ship.cpp:17090
#define SIF_NAVBUOY
Definition: ship.h:891
void render(float frametime)
char name[NAME_LENGTH]
Definition: ship.h:83
#define ENGAGE_ENEMY_ITEM
Definition: hudsquadmsg.h:45
#define TYPE_REINFORCEMENT_ITEM
bool hud_squadmsg_exist_fighters()
#define SQUAD_MSG_WING
Definition: multi.h:357
#define GM_MULTIPLAYER
Definition: systemvars.h:18
squadmate message menu disappears
Definition: gamesnd.h:98
SCP_vector< squadmsg_history > Squadmsg_history
int team
Definition: weapon.h:167
#define SEXP_FALSE
Definition: sexp.h:919
void hud_squadmsg_ship_command()
char name[NAME_LENGTH]
Definition: hudsquadmsg.h:66
char name[NAME_LENGTH]
Definition: ship.h:1517
int wingnum
Definition: ship.h:623
#define WF_WING_DEPARTING
Definition: ship.h:1502
#define MAX_STARTING_WINGS
Definition: globals.h:54
#define OBJ_WEAPON
Definition: object.h:33
int shipnum
Definition: ai.h:331
void hud_squadmsg_msg_all_fighters()
void send_player_order_packet(int type, int index, int cmd)
Definition: multimsgs.cpp:4261
int num_keys_saved
void hud_add_issued_order(char *name, int order)
void hud_squadmsg_send_to_all_fighters(int command, int player_num)
#define TYPE_REPAIR_REARM_ITEM
#define OF_PROTECTED
Definition: object.h:108
#define RF_IS_AVAILABLE
Definition: ship.h:80
#define SUBSYSTEM_TURRET
Definition: model.h:54
void hud_enemymsg_toggle()
#define HUD_SOURCE_HIDDEN
Definition: hudmessage.h:23
#define MESSAGE_DISABLE_TARGET
sexp_com_order Sexp_comm_orders[]
int uses
Definition: ship.h:85
int snd_play(game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg)
Definition: sound.cpp:517
void initItemStartOffsets(int x, int y)
int arrival_cue
Definition: missionparse.h:373
int Num_wings
Definition: ship.cpp:120
int Mbox_top_coords[GR_NUM_RESOLUTIONS][2]
Definition: hudsquadmsg.cpp:66
#define FRIENDLY_TARGET_MESSAGES
Definition: hudsquadmsg.h:102
int type_count
Definition: ship.h:417
#define AIG_TYPE_PLAYER_WING
Definition: ai.h:100
#define DISABLE_TARGET_ITEM
Definition: hudsquadmsg.h:39
int current_count
Definition: ship.h:1530
LOCAL int Msg_target_objnum
Definition: hudsquadmsg.cpp:49
float aggregate_current_hits
Definition: ship.h:419
#define AIS_GUARD_PATROL
Definition: ai.h:282
#define DEFAULT_MESSAGES
Definition: hudsquadmsg.h:83
int lssm_stage
Definition: weapon.h:216
struct squadmsg_history squadmsg_history
float current_hits
Definition: ship.h:319
#define HUD_MESSAGE_BOX
Definition: hudgauges.h:54
#define DETAIL_FLAG_HUD
Definition: systemvars.h:114
Definition: ship.h:534
int wi_flags3
Definition: weapon.h:386
int ship_get_random_ship_in_wing(int wingnum, int flags, float max_dist, int get_first)
Definition: ship.cpp:14623
void hud_squadmsg_repair_rearm_abort(int toggle_state, object *obj)
int multi_msg_eval_ship_squadmsg(int shipnum, int command, ai_info *aif, int player_num)
Definition: multi_pmsg.cpp:677
#define OVERRIDE_PROTECT_SHIP_TYPE
int idx
Definition: multiui.cpp:761
#define KEY_7
Definition: key.h:78
#define AIF_AWAITING_REPAIR
Definition: ai.h:39
sexp_node * Sexp_nodes
Definition: sexp.cpp:844
void renderString(int x, int y, const char *str)
Definition: hud.cpp:665
#define SM_MODE_REPAIR_REARM
Definition: hudsquadmsg.h:24
#define SF_DISABLED
Definition: ship.h:448
#define AI_GOAL_IGNORE_NEW
Definition: aigoals.h:57
#define MESSAGE_WARP_OUT
bool ship_useful_for_departure(int shipnum, int path_mask)
Definition: ship.cpp:17448
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
void initMiddleFrameStartOffsetY(int y)
#define SQUADMSG_HISTORY_NO_UPDATE
Definition: hudsquadmsg.h:154
int hud_disabled()
Checks if HUD disabled.
Definition: hud.cpp:1306
int wi_flags
Definition: weapon.h:384
comm_order Comm_orders[NUM_COMM_ORDER_ITEMS]
int get_parse_name_index(const char *name)
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
#define GM_DEAD
Definition: systemvars.h:25
int objnum
Definition: player.h:124
int message_is_playing()
#define WF_DEPARTURE_ORDERED
Definition: ship.h:1512
#define OBJ_INDEX(objp)
Definition: object.h:235
ship * Player_ship
Definition: ship.cpp:124
int mission_is_repair_scheduled(object *objp)
#define SM_MODE_TYPE_SELECT
Definition: hudsquadmsg.h:18
void hud_init_comm_orders()
#define NOX(s)
Definition: pstypes.h:473
int is_support_allowed(object *objp, bool do_simple_check)
Definition: ship.cpp:16749
bool end_string_at_first_hash_symbol(char *src)
Definition: parselo.cpp:3833
#define SM_MODE_WING_COMMAND
Definition: hudsquadmsg.h:22
#define WIF_BOMB
Definition: weapon.h:63
#define OBJ_SHIP
Definition: object.h:32
int hud_squadmsg_read_key(int k)
#define P_SF_REINFORCEMENT
Definition: missionparse.h:450
int hud_communications_state(ship *sp)
Definition: hudtarget.cpp:4607
int First_menu_item
void hud_squadmsg_start()
GLbitfield flags
Definition: Glext.h:6722
#define SM_MODE_SHIP_SELECT
Definition: hudsquadmsg.h:19
void initPgUpOffsets(int x, int y)
void hud_squadmsg_shortcut(int command)
int Squad_msg_mode
Definition: hudsquadmsg.cpp:42
int wing_name_lookup(const char *name, int ignore_count)
Definition: ship.cpp:12706
#define SF2_NO_BUILTIN_MESSAGES
Definition: ship.h:491
int Starting_wings[MAX_STARTING_WINGS]
Definition: ship.cpp:132
#define SM_MODE_REPAIR_REARM_ABORT
Definition: hudsquadmsg.h:25
#define AIF_BEING_REPAIRED
Definition: ai.h:40
#define MAX_KEYS_NO_SCROLL
int hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip=NULL)
GLuint const GLchar * name
Definition: Glext.h:5608
#define MESSAGE_IGNORE
int first_frame
Definition: hud.h:33
#define SUBSYSTEM_ENGINE
Definition: model.h:53
int hud_squadmsg_send_ship_command(int shipnum, int command, int send_message, int update_history, int player_num)
int Mbox_bmap_coords[GR_NUM_RESOLUTIONS][2]
Definition: hudsquadmsg.cpp:75
#define SM_MODE_REINFORCEMENTS
Definition: hudsquadmsg.h:23
void initHeaderOffsets(int x, int y)
GLbyte by
Definition: Glext.h:8237
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
uint Game_detail_flags
Definition: systemvars.cpp:52
#define SF_DEPARTING
Definition: ship.h:475
#define SQUAD_MSG_SHIP
Definition: multi.h:356
char Squad_msg_title[256]
#define MESSAGE_ON_WAY
int arrival_delay
Definition: ship.h:87
#define MAX_MENU_DISPLAY
void startFlashPageScroll(int duration=1400)
int ai_issue_rearm_request(object *requester_objp)
Definition: aicode.cpp:15446
#define TYPE_WING_ITEM
#define LOG_PLAYER_CALLED_FOR_REINFORCEMENT
Definition: missionlog.h:32
#define strcat_s(...)
Definition: safe_strings.h:68
int hud_squadmsg_do_frame()
char Comm_order_types[NUM_COMM_ORDER_TYPES][NAME_LENGTH]
#define KEY_ESC
Definition: key.h:124
#define AI_GOAL_KEEP_SAFE_DISTANCE
Definition: aigoals.h:48
#define NAME_LENGTH
Definition: globals.h:15
float frand()
Return random value in range 0.0..1.0- (1.0- means the closest number less than 1.0)
Definition: floating.cpp:35
int hud_squadmsg_can_rearm(ship *shipp)
#define AI_GOAL_DISABLE_SHIP
Definition: aigoals.h:39
int position[2]
Definition: hud.h:204
void hud_squadmsg_end()
void bm_page_in_aabitmap(int bitmapnum, int nframes)
Marks a texture as being used for this level, and is anti-aliased.
Definition: bmpman.cpp:2354
#define KEEP_SAFE_DIST_ITEM
Definition: hudsquadmsg.h:53
#define fl2i(fl)
Definition: floating.h:33
struct mmode_item mmode_item
#define MESSAGE_REARM_WARP
void hud_squadmsg_repair_rearm(int toggle_state, object *objp)
player * Player
int Msg_instance
Definition: hudsquadmsg.cpp:47
int Menu_pgdn_coords[GR_NUM_RESOLUTIONS][2]
Definition: hudsquadmsg.cpp:93
#define MESSAGE_TIME_ANYTIME
void message_send_builtin_to_player(int type, ship *shipp, int priority, int timing, int group, int delay, int multi_target, int multi_team_filter)
int special_ship
Definition: ship.h:1537
#define KEY_4
Definition: key.h:75
GLenum target
Definition: Glext.h:6872
bool active
Definition: hud.h:215
#define DEPART_ITEM
Definition: hudsquadmsg.h:56
int hud_squadmsg_hotkey_select(int k)
LOCAL ship_subsys * Msg_targeted_subsys
Definition: hudsquadmsg.cpp:50
void hud_squadmsg_save_keys(int do_scroll)
char subobj_name[MAX_NAME_LEN]
Definition: model.h:172
int Num_menu_items
#define COMM_OK
Definition: subsysdamage.h:52
void hud_squadmsg_wing_command()
#define SF_DEPARTURE_ORDERED
Definition: ship.h:471
int keys_used[]
ship_obj Ship_obj_list
Definition: ship.cpp:162
int ship_info_index
Definition: ship.h:539
#define MULTIPLAYER_MASTER
Definition: multi.h:130
void HUD_reset_clip()
Like gr_reset_clip() only it accounts for HUD jittering.
Definition: hud.cpp:3633
ubyte keyd_pressed[NUM_KEYS]
Definition: key.cpp:42
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
#define VM_PADLOCK_ANY
Definition: systemvars.h:46
#define WF_REINFORCEMENT
Definition: ship.h:1504
#define MESSAGE_YESSIR
#define SIF_FIGHTER
Definition: ship.h:885
#define AI_GOAL_CHASE_WEAPON
Definition: aigoals.h:54
#define MESSAGE_DISARM_TARGET
int Viewer_mode
Definition: systemvars.cpp:28
#define MESSAGE_DOCK_YES
void gamesnd_play_error_beep()
Definition: gamesnd.cpp:1159
#define timestamp_elapsed(stamp)
Definition: timer.h:102
int ship_get_default_orders_accepted(ship_info *sip)
Definition: ship.cpp:5480
#define TYPE_ALL_FIGHTERS_ITEM
GLsizei GLsizei GLuint * obj
Definition: Glext.h:5619
int hud_squadmsg_count_ships(int add_to_menu)
#define TBOX_FLASH_INTERVAL
Definition: hudtargetbox.h:22
int Iff_traitor
Definition: iff_defs.cpp:22
LOCAL int Msg_enemies
Definition: hudsquadmsg.cpp:51
#define AI_GOAL_CHASE
Definition: aigoals.h:29
void renderPrintf(int x, int y, const char *format,...)
Definition: hud.cpp:724
int hud_squadmsg_enemies_present()
int departure_path_mask
Definition: ship.h:619
#define STI_AI_ACCEPT_PLAYER_ORDERS
Definition: ship.h:1004
int hud_squadmsg_count_wings(int add_to_menu)
GLint GLsizei count
Definition: Gl.h:1491
GLsizei GLsizei GLchar * source
Definition: Glext.h:5625
int hud_squadmsg_get_key()
#define i2f(a)
Definition: fix.h:23
object * Player_obj
Definition: object.cpp:56
#define MESSAGE_NOSIR
int value
Definition: sexp.h:1033
GLuint GLdouble GLdouble GLint GLint order
Definition: Glext.h:10665
int Num_reinforcements
Definition: ship.cpp:121
uint flags2
Definition: ship.h:645
#define SF_DYING
Definition: ship.h:447
void hud_update_last_order(char *target, int order_source, int special_index)
#define MESSAGE_ATTACK_TARGET
int ship_index[MAX_SHIPS_PER_WING]
Definition: ship.h:1531
int emp_active_local()
Definition: emp.cpp:428
#define NUM_COMM_ORDER_TYPES
#define SQUADMSG_HISTORY_UPDATE
Definition: hudsquadmsg.h:155
int ship_get_subsys_index(ship *sp, char *ss_name, int error_bypass)
Definition: ship.cpp:13421
squadmate message menu appears
Definition: gamesnd.h:97
htarget_list keyed_targets[MAX_KEYED_TARGETS]
Definition: player.h:107
#define VM_OTHER_SHIP
Definition: systemvars.h:35
void hud_squadmsg_ship_select()
#define DISABLE_SUBSYSTEM_ITEM
Definition: hudsquadmsg.h:59
int ship_name_lookup(const char *name, int inc_players)
Definition: ship.cpp:12900
bool maybeFlashPageScroll(bool flash_fast=false)
int multi_can_message(net_player *p)
Definition: multiutil.cpp:1848
#define ABORT_REARM_REPAIR_ITEM
Definition: hudsquadmsg.h:50
false
Definition: lua.cpp:6789
uint flags
Definition: object.h:151
#define SEXP_KNOWN_FALSE
Definition: sexp.h:921
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
#define FORMATION_ITEM
Definition: hudsquadmsg.h:43
#define AI_GOAL_DESTROY_SUBSYSTEM
Definition: aigoals.h:34
char type
Definition: object.h:146
int Mbox_item_xoffset[GR_NUM_RESOLUTIONS]
Definition: hudsquadmsg.cpp:60
void hud_squadmsg_page_up()
#define WIF3_FIGHTER_INTERCEPTABLE
Definition: weapon.h:123
int hud_disabled_except_messages()
Like hud_disabled(), except messages are still drawn.
Definition: hud.cpp:1297
#define FALSE
Definition: pstypes.h:400
int multi_find_player_by_object(object *objp)
Definition: multiutil.cpp:500
#define KEY_2
Definition: key.h:73
#define LOCAL
Definition: pstypes.h:37
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
#define HUD_C_DIM
Definition: hud.h:163
#define PLAYER_FLAGS_MSG_MODE
Definition: player.h:37
#define stricmp(s1, s2)
Definition: config.h:271
LOCAL int Msg_key
Definition: hudsquadmsg.cpp:45
void hud_squadmsg_toggle()
#define AI_GOAL_FORM_ON_WING
Definition: aigoals.h:35
char ship_name[NAME_LENGTH]
Definition: ship.h:604
int hud_squadmsg_ship_order_valid(int shipnum, int order)
SCP_vector< ship_type_info > Ship_types
Definition: ship.cpp:168
void player_set_next_all_alone_msg_timestamp()
#define SM_MODE_SHIP_COMMAND
Definition: hudsquadmsg.h:21
#define MESSAGE_NO_TARGET
char * comm_order_get_text(int item)
bool hud_squadmsg_ship_valid(ship *shipp, object *objp)
int hud_squadmsg_reinforcements_available(int team)
GLint y
Definition: Gl.h:1505
void hud_squadmsg_reinforcement_select()
int flags
Definition: ship.h:1556
#define MESSAGE_TIME_SOON
#define strcpy_s(...)
Definition: safe_strings.h:67
hud_frames Mbox_gauge[NUM_MBOX_FRAMES]
Definition: hudsquadmsg.h:173
#define KEY_3
Definition: key.h:74
void renderBitmap(int x, int y)
Definition: hud.cpp:782
void initItemOffsetX(int x)