]> icculus.org git repositories - taylor/freespace2.git/blob - src/io/keycontrol.cpp
use proper FS2 demo pilot files
[taylor/freespace2.git] / src / io / keycontrol.cpp
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Io/KeyControl.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Routines to read and deal with keyboard input.
16  *
17  * $Log$
18  * Revision 1.5  2003/05/25 02:30:42  taylor
19  * Freespace 1 support
20  *
21  * Revision 1.4  2002/07/28 05:05:08  relnev
22  * removed some old stuff
23  *
24  * Revision 1.3  2002/06/18 08:58:53  relnev
25  * last few struct changes
26  *
27  * Revision 1.2  2002/06/09 04:41:21  relnev
28  * added copyright header
29  *
30  * Revision 1.1.1.1  2002/05/03 03:28:09  root
31  * Initial import.
32  *
33  * 
34  * 47    9/09/99 11:40p Dave
35  * Handle an SDL_assert() in beam code. Added supernova sounds. Play the right
36  * 2 end movies properly, based upon what the player did in the mission.
37  * 
38  * 46    9/07/99 11:26p Andsager
39  * Fix "r" targeting key, making evaluate_ship_as_closest_target() and
40  * hud_target_live_turret() consider if turret is targeting player
41  * 
42  * 45    9/03/99 1:31a Dave
43  * CD checking by act. Added support to play 2 cutscenes in a row
44  * seamlessly. Fixed super low level cfile bug related to files in the
45  * root directory of a CD. Added cheat code to set campaign mission # in
46  * main hall.
47  * 
48  * 44    9/01/99 10:09a Dave
49  * Pirate bob.
50  * 
51  * 43    8/27/99 10:36a Dave
52  * Impose a 2% penalty for hitting the shield balance key.
53  * 
54  * 42    8/27/99 9:57a Dave
55  * Enabled standard cheat codes. Allow player to continue in a campaing
56  * after using cheat codes.
57  * 
58  * 41    8/26/99 9:45a Dave
59  * First pass at easter eggs and cheats.
60  * 
61  * 40    8/24/99 1:49a Dave
62  * Fixed client-side afterburner stuttering. Added checkbox for no version
63  * checking on PXO join. Made button info passing more friendly between
64  * client and server.
65  * 
66  * 39    8/22/99 5:53p Dave
67  * Scoring fixes. Added self destruct key. Put callsigns in the logfile
68  * instead of ship designations for multiplayer players.
69  * 
70  * 38    8/19/99 10:59a Dave
71  * Packet loss detection.
72  * 
73  * 37    8/18/99 12:09p Andsager
74  * Add debug if message has no anim for message.  Make messages come from
75  * wing leader.
76  * 
77  * 36    8/05/99 2:05a Dave
78  * Whee.
79  * 
80  * 35    8/01/99 12:39p Dave
81  * Added HUD contrast control key (for nebula).
82  * 
83  * 34    7/31/99 2:30p Dave
84  * Added nifty mission message debug viewing keys.
85  * 
86  * 33    7/21/99 8:10p Dave
87  * First run of supernova effect.
88  * 
89  * 32    7/15/99 4:09p Andsager
90  * Disable cheats for FS2_DEMO
91  * 
92  * 31    7/15/99 9:20a Andsager
93  * FS2_DEMO initial checkin
94  * 
95  * 30    7/07/99 3:32p Dave
96  * Oops. Forgot to remove this.
97  * 
98  * 29    7/02/99 4:31p Dave
99  * Much more sophisticated lightning support.
100  * 
101  * 28    6/10/99 3:43p Dave
102  * Do a better job of syncing text colors to HUD gauges.
103  * 
104  * 27    6/09/99 2:55p Andsager
105  * Allow multiple asteroid subtypes (of large, medium, small) and follow
106  * family.
107  * 
108  * 26    5/24/99 5:45p Dave
109  * Added detail levels to the nebula, with a decent speedup. Split nebula
110  * lightning into its own section.
111  * 
112  * 25    5/08/99 8:25p Dave
113  * Upped object pairs. First run of nebula lightning.
114  * 
115  * 24    5/05/99 9:02p Dave
116  * Fixed D3D aabitmap rendering. Spiffed up nebula effect a bit (added
117  * rotations, tweaked values, made bitmap selection more random). Fixed
118  * D3D beam weapon clipping problem. Added D3d frame dumping.
119  * 
120  * 23    5/03/99 9:07a Dave
121  * Pirate Bob. Changed beam test code a bit.
122  * 
123  * 22    4/21/99 6:15p Dave
124  * Did some serious housecleaning in the beam code. Made it ready to go
125  * for anti-fighter "pulse" weapons. Fixed collision pair creation. Added
126  * a handy macro for recalculating collision pairs for a given object.
127  * 
128  * 21    4/16/99 5:54p Dave
129  * Support for on/off style "stream" weapons. Real early support for
130  * target-painting lasers.
131  * 
132  * 20    3/31/99 8:24p Dave
133  * Beefed up all kinds of stuff, incluging beam weapons, nebula effects
134  * and background nebulae. Added per-ship non-dimming pixel colors.
135  * 
136  * 19    3/29/99 6:17p Dave
137  * More work on demo system. Got just about everything in except for
138  * blowing ships up, secondary weapons and player death/warpout.
139  * 
140  * 18    3/28/99 5:58p Dave
141  * Added early demo code. Make objects move. Nice and framerate
142  * independant, but not much else. Don't use yet unless you're me :)
143  * 
144  * 17    3/09/99 6:24p Dave
145  * More work on object update revamping. Identified several sources of
146  * unnecessary bandwidth.
147  * 
148  * 16    2/21/99 6:01p Dave
149  * Fixed standalone WSS packets. 
150  * 
151  * 15    2/21/99 1:48p Dave
152  * Some code for monitoring datarate for multiplayer in detail.
153  * 
154  * 14    1/21/99 2:06p Dave
155  * Final checkin for multiplayer testing.
156  * 
157  * 13    1/19/99 3:57p Andsager
158  * Round 2 of variables
159  * 
160  * 12    1/12/99 12:53a Dave
161  * More work on beam weapons - made collision detection very efficient -
162  * collide against all object types properly - made 3 movement types
163  * smooth. Put in test code to check for possible non-darkening pixels on
164  * object textures.
165  * 
166  * 11    1/08/99 2:08p Dave
167  * Fixed software rendering for pofview. Super early support for AWACS and
168  * beam weapons.
169  * 
170  * 10    12/06/98 2:36p Dave
171  * Drastically improved nebula fogging.
172  * 
173  * 9     12/04/98 3:37p Andsager
174  * Added comment out asteroid launcher
175  * 
176  * 8     11/19/98 4:19p Dave
177  * Put IPX sockets back in psnet. Consolidated all multiplayer config
178  * files into one.
179  * 
180  * 7     11/05/98 5:55p Dave
181  * Big pass at reducing #includes
182  * 
183  * 6     10/26/98 9:42a Dave
184  * Early flak gun support.
185  * 
186  * 5     10/20/98 1:39p Andsager
187  * Make so sparks follow animated ship submodels.  Modify
188  * ship_weapon_do_hit_stuff() and ship_apply_local_damage() to add
189  * submodel_num.  Add submodel_num to multiplayer hit packet.
190  * 
191  * 4     10/13/98 9:28a Dave
192  * Started neatening up freespace.h. Many variables renamed and
193  * reorganized. Added AlphaColors.[h,cpp]
194  * 
195  * 3     10/09/98 2:57p Dave
196  * Starting splitting up OS stuff.
197  * 
198  * 2     10/07/98 10:53a Dave
199  * Initial checkin.
200  * 
201  * 1     10/07/98 10:49a Dave
202  * 
203  * 387   6/17/98 11:02a Lawrance
204  * show what cheat code is in the comment
205  * 
206  * 386   6/09/98 5:15p Lawrance
207  * French/German localization
208  * 
209  * 385   6/09/98 10:31a Hoffoss
210  * Created index numbers for all xstr() references.  Any new xstr() stuff
211  * added from here on out should be added to the end if the list.  The
212  * current list count can be found in FreeSpace.cpp (search for
213  * XSTR_SIZE).
214  * 
215  * 384   6/01/98 11:43a John
216  * JAS & MK:  Classified all strings for localization.
217  * 
218  * 383   5/24/98 1:46p Mike
219  * Final cheat codes.
220  * 
221  * 382   5/19/98 2:20p Mike
222  * Comment out nprintf().
223  * 
224  * 381   5/19/98 12:19p Mike
225  * Cheat codes!
226  * 
227  * 380   5/19/98 11:11a Lawrance
228  * Make 'G' only target hostiles
229  * 
230  * 379   5/18/98 11:00p Mike
231  * Adding support for cheat system.
232  * 
233  * 378   5/18/98 12:41a Allender
234  * fixed subsystem problems on clients (i.e. not reporting properly on
235  * damage indicator).  Fixed ingame join problem with respawns.  minor
236  * comm menu stuff
237  * 
238  * 377   5/17/98 1:43a Dave
239  * Eradicated chatbox problems. Remove speed match for observers. Put in
240  * help screens for PXO. Fix messaging and end mission privelges. Fixed
241  * team select screen bugs. Misc UI fixes.
242  * 
243  * 376   5/15/98 8:36p Lawrance
244  * Add 'target ship that last sent transmission' target key
245  * 
246  * 375   5/14/98 11:07a Lawrance
247  * Ensure looped sounds get stopped before stopping all channels
248  * 
249  * 374   5/12/98 11:59p Dave
250  * Put in some more functionality for Parallax Online.
251  * 
252  * 373   5/11/98 5:29p Hoffoss
253  * Added mouse button mapped to joystick button support.
254  * 
255  * 372   5/08/98 10:14a Lawrance
256  * Play sound when auto-targeting gets toggled.
257  * 
258  * 371   5/04/98 9:25a Allender
259  * don't allow time compression in multiplayer
260  * 
261  * 370   4/30/98 4:43p Allender
262  * trap player obj when changing dual fire status on ship
263  * 
264  * 369   4/30/98 4:16p Peter
265  * fixes for critical button functions when a player (client) ship is dead
266  * or dying
267  * 
268  * 368   4/27/98 9:03a Dave
269  * Fixed a multiplayer sequencing bug where paused players who were in the
270  * options screen got an SDL_assert when unpausing. Removed an optimiized
271  * build warning in keycontrol. 
272  * 
273  * 367   4/26/98 4:29p Lawrance
274  * Put back time compression keys... somehow they were trashed by a later
275  * checkin.
276  * 
277  * 366   4/25/98 5:36p Mike
278  * Prevent player warpout if engine < 10%.
279  * 
280  * $NoKeywords: $
281  */
282
283 #include "pstypes.h"
284 #include "linklist.h"
285 #include "key.h"
286 #include "joy.h"
287 #include "timer.h"
288 #include "ship.h"
289 #include "player.h"
290 #include "weapon.h"
291 #include "hud.h"
292 #include "contexthelp.h"
293 #include "gamesequence.h"
294 #include "osapi.h"
295 #include "missiongoals.h"
296 #include "hud.h"
297 #include "hudtarget.h"
298 #include "optionsmenu.h"
299 #include "freespace.h"
300 #include "controlsconfig.h"
301 #include "mouse.h"
302 #include "hudets.h"
303 #include "multi.h"
304 #include "multiutil.h"
305 #include "sound.h"
306 #include "gamesnd.h"
307 #include "bmpman.h"
308 #include "hudsquadmsg.h"
309 #include "eventmusic.h"
310 #include "animplay.h"
311 #include "freespace.h"
312 #include "cmeasure.h"
313 #include "missionhotkey.h"
314 #include "afterburner.h"
315 #include "missionparse.h"
316 #include "hudescort.h"
317 #include "hudshield.h"
318 #include "multiutil.h"
319 #include "multimsgs.h"
320 #include "keycontrol.h"
321 #include "shiphit.h"
322 #include "shipfx.h"
323 #include "hud.h"
324 #include "hudobserver.h"
325 #include "missionlog.h"
326 #include "hudtargetbox.h"
327 #include "popup.h"
328 #include "objcollide.h"
329 #include "hudconfig.h"
330 #include "missioncampaign.h"
331 #include "rtvoice.h"
332 #include "multi_respawn.h"
333 #include "multi_pmsg.h"
334 #include "crypt.h"
335 #include "ui.h"
336 #include "multi_pause.h"
337 #include "multi_observer.h"
338 #include "multi_endgame.h"
339 #include "beam.h"
340 #include "neblightning.h"
341 #include "supernova.h"
342 #include "missionmessage.h"
343 #include "mainhallmenu.h"
344 #include "aigoals.h"
345 #include "localize.h"
346
347 // --------------------------------------------------------------
348 // Global to file 
349 // --------------------------------------------------------------
350
351 // --------------------------------------------------------------
352 // Externals
353 // --------------------------------------------------------------
354 typedef struct asteroid_field {
355         vector  min_bound;                                              //      Minimum range of field.
356         vector  max_bound;                                              //      Maximum range of field.
357         vector  vel;                                                            //      Average asteroid moves at this velocity.
358         float           speed;                                                  // Average speed of field
359         int             num_initial_asteroids;          //      Number of asteroids at creation.
360 } asteroid_field;
361
362 #define CHEAT_BUFFER_LEN        20
363 #define CHEATSPOT                               (CHEAT_BUFFER_LEN - 1)
364
365 char CheatBuffer[CHEAT_BUFFER_LEN+1];
366
367 #if defined(FS2_DEMO)
368         const char *Cheat_code_demo = NOX("33BE^(8]C01(:=BHt");
369 #elif defined(MAKE_FS1)
370         const char *Cheat_code_gr = NOX("BNdEgDB\\s?0XD1?0)");          // de:www.volition-inc.com
371         const char *Cheat_code = NOX("E5B?(\"=H'5UTE$o%D");                     // www.volition-inc.com
372         const char *Cheat_code_movies = NOX("iC:1C06,'00SoXyY6");               // freespacestandsalone
373 #else
374         const char *Cheat_code = NOX("33BE^(8]C01(:=BHt");                                      // www.freespace2.com
375         const char *Cheat_code_fish = NOX("bDc9y+$;#AIDRoouM");                 // vasudanswuvfishes
376         const char *Cheat_code_headz = NOX("!;:::@>F7L?@@2:@A");                        // humanheadsinside.
377         const char *Cheat_code_tooled = NOX("sipp-^rM@L!U^usjX");               // tooledworkedowned
378         const char *Cheat_code_pirate = NOX("MAP4YP[4=-2uC(yJ^");               // arrrrwalktheplank    
379         const char *Cheat_code_skip = NOX("7!ICkSI\"(8n3JesBP");                        // skipmemymissionyo
380 #endif
381                                                                                   // 666)6=N79+Z45=BE0e
382 int Tool_enabled = 0;
383
384         /*
385 #else 
386         // list of the cheat codes
387         //#ifdef INTERPLAYQA
388         // "DavidPerry" NOX("0!XZQ*K.pu");
389         // NOX("&BvWJe=a?$VP*=@2W,2Y"); // Super-secret 20 character string!
390         //NOX("STs`nHqW\\lv#KD_aCSWN"); //      solveditonceandforall (note double \\ as string contains \.
391         //XSTR:OFF
392         char *Cheat_code_in_game = NOX("///FES)P<A5=7CCB!n10"); //      www.volition-inc.com
393         char *Cheat_code_movies =  NOX("&BvWJe=a?$VP*=@2W,2Y"); // freespacestandsalone
394         char *Cheat_code_pirate = NOX("%,sPzoE>\\+_(Qs#+h-8o");                         // arrwalktheplankmatey
395         //XSTR:ON
396 #endif
397         */
398
399 int All_movies_enabled = 0;
400
401 //int Debug_allowed = 0;
402
403 //#endif
404
405 extern int AI_watch_object;
406 extern int Countermeasures_enabled;
407
408 extern fix Game_time_compression;
409
410 extern float do_subobj_hit_stuff(object *ship_obj, object *other_obj, vector *hitpos, float damage);
411
412 extern void mission_goal_mark_all_true( int type );
413
414 int Normal_key_set[] = {
415         TARGET_NEXT,
416         TARGET_PREV,
417         TARGET_NEXT_CLOSEST_HOSTILE,
418         TARGET_PREV_CLOSEST_HOSTILE,
419         TARGET_NEXT_CLOSEST_FRIENDLY,
420         TARGET_PREV_CLOSEST_FRIENDLY,
421         TARGET_TARGETS_TARGET,
422         TARGET_SHIP_IN_RETICLE,
423         TARGET_LAST_TRANMISSION_SENDER,
424         TARGET_CLOSEST_SHIP_ATTACKING_TARGET,
425         TARGET_CLOSEST_SHIP_ATTACKING_SELF,
426         STOP_TARGETING_SHIP,
427         TOGGLE_AUTO_TARGETING,
428         TARGET_SUBOBJECT_IN_RETICLE,
429         TARGET_PREV_SUBOBJECT,
430         TARGET_NEXT_SUBOBJECT,
431         STOP_TARGETING_SUBSYSTEM,
432
433         TARGET_NEXT_UNINSPECTED_CARGO,
434         TARGET_PREV_UNINSPECTED_CARGO,
435         TARGET_NEWEST_SHIP,
436         TARGET_NEXT_LIVE_TURRET,
437         TARGET_PREV_LIVE_TURRET,
438         TARGET_NEXT_BOMB,
439         TARGET_PREV_BOMB,
440
441         ATTACK_MESSAGE,
442         DISARM_MESSAGE,
443         DISABLE_MESSAGE,
444         ATTACK_SUBSYSTEM_MESSAGE,
445         CAPTURE_MESSAGE,
446         ENGAGE_MESSAGE,
447         FORM_MESSAGE,
448         PROTECT_MESSAGE,
449         COVER_MESSAGE,
450         WARP_MESSAGE,
451         REARM_MESSAGE,
452         IGNORE_MESSAGE,
453         SQUADMSG_MENU,
454
455         VIEW_CHASE,
456         VIEW_OTHER_SHIP,
457
458         SHOW_GOALS,
459         END_MISSION,
460
461         ADD_REMOVE_ESCORT,
462         ESCORT_CLEAR,
463         TARGET_NEXT_ESCORT_SHIP,
464
465         XFER_SHIELD,
466         XFER_LASER,
467         INCREASE_SHIELD,
468         INCREASE_WEAPON,
469         INCREASE_ENGINE,
470         DECREASE_SHIELD,
471         DECREASE_WEAPON,
472         DECREASE_ENGINE,
473         ETS_EQUALIZE,
474         SHIELD_EQUALIZE,
475         SHIELD_XFER_TOP,
476         SHIELD_XFER_BOTTOM,
477         SHIELD_XFER_RIGHT,
478         SHIELD_XFER_LEFT,
479
480         CYCLE_NEXT_PRIMARY,
481         CYCLE_PREV_PRIMARY,
482         CYCLE_SECONDARY,
483         CYCLE_NUM_MISSLES,
484         RADAR_RANGE_CYCLE,
485
486         MATCH_TARGET_SPEED,
487         TOGGLE_AUTO_MATCH_TARGET_SPEED,
488
489         VIEW_EXTERNAL,
490         VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK,
491         LAUNCH_COUNTERMEASURE,
492         ONE_THIRD_THROTTLE,
493         TWO_THIRDS_THROTTLE,
494         PLUS_5_PERCENT_THROTTLE,
495         MINUS_5_PERCENT_THROTTLE,
496         ZERO_THROTTLE,
497         MAX_THROTTLE,
498
499         TARGET_CLOSEST_REPAIR_SHIP,
500
501         MULTI_MESSAGE_ALL,
502         MULTI_MESSAGE_FRIENDLY,
503         MULTI_MESSAGE_HOSTILE,
504         MULTI_MESSAGE_TARGET,
505         MULTI_OBSERVER_ZOOM_TO,
506
507         TIME_SPEED_UP,
508         TIME_SLOW_DOWN,
509 #ifndef MAKE_FS1
510         TOGGLE_HUD_CONTRAST,
511
512 #ifndef FS2_DEMO
513         MULTI_TOGGLE_NETINFO,
514         MULTI_SELF_DESTRUCT
515 #endif
516 #endif
517 };
518
519 int Dead_key_set[] = {
520         TARGET_NEXT,
521         TARGET_PREV,
522         TARGET_NEXT_CLOSEST_HOSTILE,
523         TARGET_PREV_CLOSEST_HOSTILE,
524         TARGET_NEXT_CLOSEST_FRIENDLY,
525         TARGET_PREV_CLOSEST_FRIENDLY,
526         TARGET_TARGETS_TARGET,
527         TARGET_CLOSEST_SHIP_ATTACKING_TARGET,
528         STOP_TARGETING_SHIP,
529         TOGGLE_AUTO_TARGETING,
530         TARGET_SUBOBJECT_IN_RETICLE,
531         TARGET_PREV_SUBOBJECT,
532         TARGET_NEXT_SUBOBJECT,
533         STOP_TARGETING_SUBSYSTEM,
534         TARGET_NEWEST_SHIP,
535         TARGET_NEXT_LIVE_TURRET,
536         TARGET_PREV_LIVE_TURRET,
537         TARGET_NEXT_BOMB,
538         TARGET_PREV_BOMB,
539
540         VIEW_CHASE,
541         VIEW_OTHER_SHIP,
542
543         SHOW_GOALS,
544
545         ADD_REMOVE_ESCORT,
546         ESCORT_CLEAR,
547         TARGET_NEXT_ESCORT_SHIP,
548         TARGET_CLOSEST_REPAIR_SHIP,     
549
550         MULTI_MESSAGE_ALL,
551         MULTI_MESSAGE_FRIENDLY,
552         MULTI_MESSAGE_HOSTILE,
553         MULTI_MESSAGE_TARGET,
554         MULTI_OBSERVER_ZOOM_TO,
555
556         TIME_SPEED_UP,
557         TIME_SLOW_DOWN
558 };
559
560 int Critical_key_set[] = {              
561         CYCLE_SECONDARY,                        
562         CYCLE_NUM_MISSLES,                      
563         INCREASE_WEAPON,                        
564         DECREASE_WEAPON,        
565         INCREASE_SHIELD,                        
566         DECREASE_SHIELD,                        
567         INCREASE_ENGINE,                        
568         DECREASE_ENGINE,                        
569         ETS_EQUALIZE,
570         SHIELD_EQUALIZE,                        
571         SHIELD_XFER_TOP,                        
572         SHIELD_XFER_BOTTOM,                     
573         SHIELD_XFER_LEFT,                       
574         SHIELD_XFER_RIGHT,                      
575         XFER_SHIELD,                    
576         XFER_LASER,                     
577 };
578
579 int Non_critical_key_set[] = {
580         CYCLE_NEXT_PRIMARY,             
581         CYCLE_PREV_PRIMARY,                     
582         MATCH_TARGET_SPEED,                     
583         TOGGLE_AUTO_MATCH_TARGET_SPEED,                 
584         TARGET_NEXT,    
585         TARGET_PREV,                    
586         TARGET_NEXT_CLOSEST_HOSTILE,                    
587         TARGET_PREV_CLOSEST_HOSTILE,                    
588         TOGGLE_AUTO_TARGETING,                  
589         TARGET_NEXT_CLOSEST_FRIENDLY,                   
590         TARGET_PREV_CLOSEST_FRIENDLY,                   
591         TARGET_SHIP_IN_RETICLE,                 
592         TARGET_LAST_TRANMISSION_SENDER,
593         TARGET_CLOSEST_REPAIR_SHIP,                     
594         TARGET_CLOSEST_SHIP_ATTACKING_TARGET,                   
595         STOP_TARGETING_SHIP,                    
596         TARGET_CLOSEST_SHIP_ATTACKING_SELF,                     
597         TARGET_TARGETS_TARGET,                  
598         TARGET_SUBOBJECT_IN_RETICLE,                    
599         TARGET_PREV_SUBOBJECT,                  
600         TARGET_NEXT_SUBOBJECT,                  
601         STOP_TARGETING_SUBSYSTEM,
602         TARGET_NEXT_BOMB,
603         TARGET_PREV_BOMB,
604         TARGET_NEXT_UNINSPECTED_CARGO,
605         TARGET_PREV_UNINSPECTED_CARGO,
606         TARGET_NEWEST_SHIP,
607         TARGET_NEXT_LIVE_TURRET,
608         TARGET_PREV_LIVE_TURRET,
609         ATTACK_MESSAGE,
610         DISARM_MESSAGE,
611         DISABLE_MESSAGE,
612         ATTACK_SUBSYSTEM_MESSAGE,
613         CAPTURE_MESSAGE,
614         ENGAGE_MESSAGE,
615    FORM_MESSAGE,
616         PROTECT_MESSAGE,
617         COVER_MESSAGE,
618         WARP_MESSAGE,
619         IGNORE_MESSAGE,
620         REARM_MESSAGE,
621         VIEW_CHASE,
622         VIEW_EXTERNAL,
623         VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK,
624         VIEW_OTHER_SHIP,
625         RADAR_RANGE_CYCLE,
626         SQUADMSG_MENU,
627         SHOW_GOALS,
628         END_MISSION,
629         ADD_REMOVE_ESCORT,
630         ESCORT_CLEAR,
631         TARGET_NEXT_ESCORT_SHIP,        
632         MULTI_MESSAGE_ALL,
633         MULTI_MESSAGE_FRIENDLY,
634         MULTI_MESSAGE_HOSTILE,
635         MULTI_MESSAGE_TARGET,
636         MULTI_OBSERVER_ZOOM_TO,
637 #ifndef MAKE_FS1
638         TOGGLE_HUD_CONTRAST,
639
640 #ifndef FS2_DEMO
641         MULTI_TOGGLE_NETINFO,
642         MULTI_SELF_DESTRUCT
643 #endif
644 #endif
645 };
646
647
648 // set sizes of the key sets automatically
649 int Normal_key_set_size = sizeof(Normal_key_set) / sizeof(int);
650 int Dead_key_set_size = sizeof(Dead_key_set) / sizeof(int);
651 int Critical_key_set_size = sizeof(Critical_key_set) / sizeof(int);
652 int Non_critical_key_set_size = sizeof(Non_critical_key_set) / sizeof(int);
653
654 // --------------------------------------------------------------
655 // routine to process keys used only for debugging
656 // --------------------------------------------------------------
657 //#ifndef NDEBUG
658
659 void debug_cycle_player_ship(int delta)
660 {
661         if ( Player_obj == NULL )
662                 return;
663
664         int si_index = Ships[Player_obj->instance].ship_info_index;
665         int sanity = 0;
666         ship_info       *sip;
667         while ( TRUE ) {
668                 si_index += delta;
669                 if ( si_index > MAX_SHIP_TYPES ){
670                         si_index = 0;
671                 }
672                 if ( si_index < 0 ){
673                         si_index = MAX_SHIP_TYPES - 1;
674                 }
675                 sip = &Ship_info[si_index];
676                 if ( sip->flags & SIF_PLAYER_SHIP ){
677                         break;
678                 }
679
680                 // just in case
681                 sanity++;
682                 if ( sanity > MAX_SHIP_TYPES ){
683                         break;
684                 }
685         }
686
687         change_ship_type(Player_obj->instance, si_index);
688         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Player ship changed to %s", 0), Ship_info[si_index].name);                 
689 }
690
691 // cycle targeted ship to next ship in that species
692 void debug_cycle_targeted_ship(int delta)
693 {
694         object          *objp;
695         ship_info       *sip;
696         int                     si_index, species;
697         char                    name[NAME_LENGTH];
698
699         if ( Player_ai->target_objnum == -1 )
700                 return;
701
702         objp = &Objects[Player_ai->target_objnum];
703         if ( objp->type != OBJ_SHIP )
704                 return;
705
706         si_index = Ships[objp->instance].ship_info_index;
707         SDL_assert(si_index != -1 );
708         species = Ship_info[si_index].species;
709
710         int sanity = 0;
711
712         while ( TRUE ) {
713                 si_index += delta;
714                 if ( si_index > MAX_SHIP_TYPES )
715                         si_index = 0;
716                 if ( si_index < 0 )
717                         si_index = MAX_SHIP_TYPES-1;
718
719         
720                 sip = &Ship_info[si_index];
721         
722                 // if it has test in the name, jump over it
723                 SDL_strlcpy(name, sip->name, SDL_arraysize(name));
724                 SDL_strlwr(name);
725                 if ( strstr(name,NOX("test")) != NULL )
726                         continue;
727
728                 if ( sip->species == species && (sip->flags & (SIF_FIGHTER | SIF_BOMBER | SIF_TRANSPORT) ) )
729                         break;
730
731                 // just in case
732                 sanity++;
733                 if ( sanity > MAX_SHIP_TYPES )
734                         break;
735         }
736
737         change_ship_type(objp->instance, si_index);
738         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Changed player target to %s", 1), Ship_info[si_index].name);                       
739 }
740
741 void debug_max_secondary_weapons(object *objp)
742 {
743         int index;
744         ship *shipp = &Ships[objp->instance];
745         ship_info *sip = &Ship_info[shipp->ship_info_index];
746
747         for ( index = 0; index < MAX_SECONDARY_BANKS; index++ ) {
748                 shipp->weapons.secondary_bank_ammo[index] = sip->secondary_bank_ammo_capacity[index];
749         }
750 }
751
752 void debug_change_song(int delta)
753 {
754         char buf[256];
755         if ( event_music_next_soundtrack(delta) != -1 ) {
756                 event_music_get_soundtrack_name(buf, sizeof(buf));
757                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Soundtrack changed to: %s", 2), buf);
758
759         } else {
760                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Event music is not playing", 3));
761         }
762 }
763
764 //extern void set_global_ignore_object(int objnum);
765
766 extern void hud_target_asteroid();
767 extern int Framerate_delay;
768
769 extern void snd_stop_any_sound();
770
771 void process_debug_keys(int k)
772 {
773 #ifdef INTERPLAYQA
774         if ( !Debug_allowed )
775                 return;
776 #endif
777
778         // if ( (k & KEY_DEBUGGED) && (Game_mode & GM_RECORDING_DEMO) )
779                 // return;
780
781         switch (k) {
782                 case KEY_DEBUGGED + SDLK_h:
783                         hud_target_toggle_hidden_from_sensors();
784                         break;
785
786                 case KEY_DEBUGGED + SDLK_f:
787                         /*
788                         int i;
789                         for (i=0; i<NUM_HUD_GAUGES; i++) {
790                                 hud_gauge_start_flash(i);
791                         }
792                         */
793                         extern int wacky_scheme;
794                         if(wacky_scheme == 3){
795                                 wacky_scheme = 0;
796                         } else {
797                                 wacky_scheme++;
798                         }
799                         break;
800                 
801                 case KEY_DEBUGGED + KEY_ALTED + SDLK_f:
802                         Framerate_delay += 10;
803                         HUD_printf(XSTR( "Framerate delay increased to %i milliseconds per frame.", 4), Framerate_delay);
804                         break;
805
806                 case KEY_DEBUGGED + KEY_ALTED + KEY_SHIFTED + SDLK_f:
807                         Framerate_delay -= 10;
808                         if (Framerate_delay < 0)
809                                 Framerate_delay = 0;
810
811                         HUD_printf(XSTR( "Framerate delay decreased to %i milliseconds per frame.", 5), Framerate_delay);
812                         break;
813
814                 case KEY_DEBUGGED + SDLK_c:
815                 case KEY_DEBUGGED1 + SDLK_c:
816                         // hud_enemymsg_toggle();
817                         if(Player_obj->flags & OF_COLLIDES){
818                                 obj_set_flags(Player_obj, Player_obj->flags & ~(OF_COLLIDES));
819                                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, "Player no longer collides");
820                         } else {
821                                 obj_set_flags(Player_obj, Player_obj->flags | OF_COLLIDES);
822                                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, "Player collides");
823                         }
824                         break;
825
826                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_c:
827                 case KEY_DEBUGGED1 + KEY_SHIFTED + SDLK_c:
828                         Countermeasures_enabled = !Countermeasures_enabled;
829                         HUD_printf(XSTR( "Countermeasure firing: %s", 6), Countermeasures_enabled ? XSTR( "ENABLED", 7) : XSTR( "DISABLED", 8));
830                         break;
831
832                 case KEY_DEBUGGED + SDLK_e:
833                         gameseq_post_event(GS_EVENT_EVENT_DEBUG);
834                         break;
835
836                 case KEY_DEBUGGED + SDLK_COMMA:
837                         if ( Game_time_compression > (F1_0/4) ){                // can't compress below 0.25
838                                 Game_time_compression /= 2;
839                         }
840                         break;
841                 case KEY_DEBUGGED + SDLK_PERIOD:
842                         if ( Game_time_compression < (F1_0*8) ){
843                                 Game_time_compression *= 2;
844                         }
845                         break;
846
847                 //      Kill! the currently targeted ship.
848                 case KEY_DEBUGGED + SDLK_k:
849                 case KEY_DEBUGGED1 + SDLK_k:
850                         if (Player_ai->target_objnum != -1) {
851                                 object  *objp = &Objects[Player_ai->target_objnum];
852
853                                 switch (objp->type) {
854                                 case OBJ_SHIP:
855                                         ship_apply_local_damage( objp, Player_obj, &objp->pos, 100000.0f, MISS_SHIELDS, CREATE_SPARKS);
856                                         ship_apply_local_damage( objp, Player_obj, &objp->pos, 1.0f, MISS_SHIELDS, CREATE_SPARKS);
857                                         break;
858                                 case OBJ_WEAPON:
859                                         Weapons[objp->instance].lifeleft = 0.01f;
860                                         break;
861                                 }
862                         }
863
864                         break;
865                 
866                 // play the next mission message
867                 case KEY_DEBUGGED + SDLK_v:
868                         extern int Message_debug_index;
869                         extern int Num_messages_playing;
870                         // stop any other messages
871                         if(Num_messages_playing){
872                                 message_kill_all(1);
873                         }
874
875                         // next message
876                         if(Message_debug_index >= Num_messages - 1){
877                                 Message_debug_index = Num_builtin_messages;
878                         } else {
879                                 Message_debug_index++;
880                         }
881                         
882                         // play the message
883                         message_send_unique_to_player( Messages[Message_debug_index].name, Message_waves[Messages[Message_debug_index].wave_info.index].name, MESSAGE_SOURCE_SPECIAL, MESSAGE_PRIORITY_HIGH, 0, 0 );                    
884                         if (Messages[Message_debug_index].avi_info.index == -1) {
885                                 HUD_printf("No anim set for message \"%s\"; None will play!", Messages[Message_debug_index].name);
886                         }
887                         break;
888
889                 // play the previous mission message
890                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_v:
891                         extern int Message_debug_index;
892                         extern int Num_messages_playing;
893                         // stop any other messages
894                         if(Num_messages_playing){
895                                 message_kill_all(1);
896                         }
897
898                         // go maybe go down one
899                         if(Message_debug_index == Num_builtin_messages - 1){
900                                 Message_debug_index = Num_builtin_messages;
901                         } else if(Message_debug_index > Num_builtin_messages){
902                                 Message_debug_index--;
903                         }
904                         
905                         // play the message
906                         message_send_unique_to_player( Messages[Message_debug_index].name, Message_waves[Messages[Message_debug_index].wave_info.index].name, MESSAGE_SOURCE_SPECIAL, MESSAGE_PRIORITY_HIGH, 0, 0 );
907                         if (Messages[Message_debug_index].avi_info.index == -1) {
908                                 HUD_printf("No avi associated with this message; None will play!");
909                         }
910                         break;
911
912                 // reset to the beginning of mission messages
913                 case KEY_DEBUGGED + KEY_ALTED + SDLK_v:
914                         extern int Message_debug_index;
915                         Message_debug_index = Num_builtin_messages - 1;
916                         HUD_printf("Resetting to first mission message");
917                         break;
918
919                 //      Kill! the currently targeted ship.
920                 case KEY_DEBUGGED + KEY_ALTED + KEY_SHIFTED + SDLK_k:
921                 case KEY_DEBUGGED1 + KEY_ALTED + KEY_SHIFTED + SDLK_k:
922                         if (Player_ai->target_objnum != -1) {
923                                 object  *objp = &Objects[Player_ai->target_objnum];
924
925                                 if (objp->type == OBJ_SHIP) {
926                                         ship_apply_local_damage( objp, Player_obj, &objp->pos, Ship_info[Ships[objp->instance].ship_info_index].initial_hull_strength * 0.1f + 10.0f, MISS_SHIELDS, CREATE_SPARKS);
927                                 }
928                         }
929                         break;
930
931                         //      Kill the currently targeted subsystem.
932                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_k:
933                 case KEY_DEBUGGED1 + KEY_SHIFTED + SDLK_k:
934                         if ((Player_ai->target_objnum != -1) && (Player_ai->targeted_subsys != NULL)) {
935                                 object  *objp = &Objects[Player_ai->target_objnum];
936                                 if ( objp->type == OBJ_SHIP ) {
937                                         ship            *sp = &Ships[objp->instance];
938                                         vector  g_subobj_pos;
939
940                                         get_subsystem_world_pos(objp, Player_ai->targeted_subsys, &g_subobj_pos);
941
942                                         do_subobj_hit_stuff(objp, Player_obj, &g_subobj_pos, (float) -Player_ai->targeted_subsys->system_info->type); //100.0f);
943
944                                         if ( sp->subsys_info[SUBSYSTEM_ENGINE].current_hits <= 0.0f ) {
945                                                 mission_log_add_entry(LOG_SHIP_DISABLED, sp->ship_name, NULL );
946                                                 sp->flags |= SF_DISABLED;                               // add the disabled flag
947                                         }
948
949                                         if ( sp->subsys_info[SUBSYSTEM_TURRET].current_hits <= 0.0f ) {
950                                                 mission_log_add_entry(LOG_SHIP_DISARMED, sp->ship_name, NULL );
951                                                 // sp->flags |= SF_DISARMED;                            // add the disarmed flag
952                                         }
953                                 }
954                         }
955                         break;
956
957                 case KEY_DEBUGGED + KEY_ALTED + SDLK_k:
958                 case KEY_DEBUGGED1 + KEY_ALTED + SDLK_k:
959                         {
960                                 float   shield, integrity;
961                                 vector  pos, randvec;
962
963                                 vm_vec_rand_vec_quick(&randvec);
964                                 vm_vec_scale_add(&pos, &Player_obj->pos, &randvec, Player_obj->radius);
965                         ship_apply_local_damage(Player_obj, Player_obj, &pos, 25.0f, MISS_SHIELDS, CREATE_SPARKS);
966                         hud_get_target_strength(Player_obj, &shield, &integrity);
967                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "You knocked yourself down to %7.3f percent hull.\n", 9), 100.0f * integrity);
968                         break;
969                         }
970                         
971                 //      Whack down the player's shield and hull by a little more than 50%
972                 //      Select next object to be viewed by AI.
973                 case KEY_DEBUGGED + SDLK_i:
974                 case KEY_DEBUGGED1 + SDLK_i:
975                         Player_obj->flags ^= OF_INVULNERABLE;
976                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "You are %s", 10), Player_obj->flags & OF_INVULNERABLE ? XSTR( "now INVULNERABLE!", 11) : XSTR( "no longer invulnerable...", 12));
977                         break;
978
979                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_i:
980                 case KEY_DEBUGGED1 + KEY_SHIFTED + SDLK_i:
981                         if (Player_ai->target_objnum != -1) {
982                                 object  *objp = &Objects[Player_ai->target_objnum];
983
984                                 objp->flags ^= OF_INVULNERABLE;
985                                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Player's target [%s] is %s", 13), Ships[objp->instance].ship_name, objp->flags & OF_INVULNERABLE ? XSTR( "now INVULNERABLE!", 11) : XSTR( "no longer invulnerable...", 12));
986                         }
987                         break;
988 /*
989                 case KEY_DEBUGGED + KEY_ALTED + SDLK_i:
990                         if (Player_ai->target_objnum != -1)
991                                 set_global_ignore_object(Player_ai->target_objnum);
992                         break;
993 */
994
995                 case KEY_DEBUGGED + SDLK_n:
996                         AI_watch_object++;
997                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Spewing debug info about object #%d", 14), AI_watch_object);
998                         break;
999
1000                 case KEY_DEBUGGED + SDLK_o:
1001 #ifdef MAKE_FS1
1002                 case KEY_DEBUGGED1 + SDLK_o:
1003 #endif
1004                         toggle_player_object();
1005                         break;                          
1006
1007                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_o:
1008                         extern int Debug_octant;
1009                         if(Debug_octant == 7){
1010                                 Debug_octant = -1;
1011                         } else {
1012                                 Debug_octant++;
1013                         }
1014                         nprintf(("General", "Debug_octant == %d\n", Debug_octant));
1015                         break;
1016
1017 #ifndef MAKE_FS1
1018                 case KEY_DEBUGGED + SDLK_p:
1019                         supernova_start(20);
1020                         break;
1021 #endif
1022
1023                 case KEY_DEBUGGED + SDLK_w:
1024                 case KEY_DEBUGGED1 + SDLK_w:
1025                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_w:
1026                 case KEY_DEBUGGED1 + KEY_SHIFTED + SDLK_w:
1027                         // temp code for testing purposes, toggles weapon energy cheat
1028                         Weapon_energy_cheat = !Weapon_energy_cheat;
1029                         if (Weapon_energy_cheat) {
1030                                 if (k & KEY_SHIFTED)
1031                                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Weapon energy and missile count will always be at full ALL SHIPS!", 15));
1032                                 else
1033                                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Weapon energy and missile count will always be at full for player", 16));
1034
1035                                 debug_max_secondary_weapons(Player_obj);
1036                                 if (k & KEY_SHIFTED) {
1037                                         object  *objp;
1038
1039                                         for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) )
1040                                                 if (objp->type == OBJ_SHIP)
1041                                                         debug_max_secondary_weapons(objp);
1042                                 }
1043
1044                         } else
1045                                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Normal weapon energy system / missile count restored", 17));
1046
1047                         break;
1048
1049                 case KEY_DEBUGGED + SDLK_g:
1050 #ifdef MAKE_FS1
1051                 case KEY_DEBUGGED1 + SDLK_g:
1052 #endif
1053                         mission_goal_mark_all_true( PRIMARY_GOAL );
1054                         break;
1055
1056                 case KEY_DEBUGGED + SDLK_g + KEY_SHIFTED:
1057 #ifdef MAKE_FS1
1058                 case KEY_DEBUGGED1 + SDLK_g + KEY_SHIFTED:
1059 #endif
1060                         mission_goal_mark_all_true( SECONDARY_GOAL );
1061                         break;
1062
1063                 case KEY_DEBUGGED + SDLK_g + KEY_ALTED:
1064 #ifdef MAKE_FS1
1065                 case KEY_DEBUGGED1 + SDLK_g + KEY_ALTED:
1066 #endif
1067                         mission_goal_mark_all_true( BONUS_GOAL );
1068                         break;
1069
1070                 case KEY_DEBUGGED + SDLK_9: {
1071                 case KEY_DEBUGGED1 + SDLK_9:
1072                         ship* shipp;
1073
1074                         shipp = &Ships[Player_obj->instance];
1075                         shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]++;
1076                         if ( shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank] >= Num_weapon_types )
1077                                 shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank] = First_secondary_index;
1078
1079                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary Weapon forced to %s", 18), Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name);
1080                         break;
1081                 }
1082
1083 #ifdef MAKE_FS1
1084                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_9: {
1085                 case KEY_DEBUGGED1 + KEY_SHIFTED + SDLK_9:
1086                         ship* shipp;
1087
1088                         shipp = &Ships[Player_obj->instance];
1089                         shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]--;
1090                         if ( shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank] < 0)
1091                                 shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank] = Num_weapon_types - 1;
1092
1093                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary Weapon forced to %s", 18), Weapon_info[shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank]].name);
1094                         break;
1095                 }
1096 #endif
1097
1098 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
1099                 case KEY_DEBUGGED + SDLK_u: {
1100                 case KEY_DEBUGGED1 + SDLK_u:
1101                         // launch asteroid
1102                         extern asteroid_field Asteroid_field;
1103                         object *asteroid_create(asteroid_field *asfieldp, int asteroid_type, int subtype);
1104                         object *objp = asteroid_create(&Asteroid_field, 0, 0);
1105                         vector vel;
1106                         vm_vec_copy_scale(&vel, &Player_obj->orient.v.fvec, 50.0f);
1107                         objp->phys_info.vel = vel;
1108                         objp->phys_info.desired_vel = vel;
1109                         objp->pos = Player_obj->pos;
1110                         //mission_goal_mark_all_true( PRIMARY_GOAL );
1111                         break;
1112                 }
1113 #endif
1114
1115                 case KEY_DEBUGGED + SDLK_0: {
1116                 case KEY_DEBUGGED1 + SDLK_0:
1117                         ship* shipp;
1118
1119                         shipp = &Ships[Player_obj->instance];
1120                         shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]++;
1121                         if ( shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank] >= First_secondary_index )
1122                                 shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank] = 0;
1123
1124                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Primary Weapon forced to %s", 19), Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name);
1125                         break;
1126                 }
1127
1128                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_0: {
1129                 case KEY_DEBUGGED1 + KEY_SHIFTED + SDLK_0:
1130                         ship* shipp;
1131
1132                         shipp = &Ships[Player_obj->instance];
1133                         shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]--;
1134                         if ( shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank] < 0)
1135                                 shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank] = First_secondary_index-1 ;
1136
1137                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Primary Weapon forced to %s", 19), Weapon_info[shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank]].name);
1138                         break;
1139                 }
1140
1141                 case KEY_DEBUGGED + SDLK_j: {
1142                         int new_pattern = event_music_return_current_pattern();
1143
1144                         new_pattern++;
1145                         if ( new_pattern >= MAX_PATTERNS )
1146                                 new_pattern = 0;
1147
1148                         event_music_change_pattern(new_pattern);
1149                         break;
1150                 }
1151
1152                 case KEY_DEBUGGED + SDLK_m: {
1153                         if ( Event_music_enabled ) {
1154                                 event_music_disable();
1155                                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Event music disabled", 20));
1156
1157                         } else {
1158                                 event_music_enable();
1159                                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Event music enabled", 21));
1160                         }
1161
1162                         break;
1163                 }
1164
1165                 case KEY_DEBUGGED + SDLK_r: {
1166                 // case KEY_DEBUGGED1 + SDLK_r:
1167                         if (Player_ai->target_objnum != -1)
1168                                 ai_issue_rearm_request(&Objects[Player_ai->target_objnum]);
1169                         else
1170                                 ai_issue_rearm_request(Player_obj);
1171
1172                         break;
1173                 }
1174
1175                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_UP:
1176                         Game_detail_level++;
1177                         HUD_printf( XSTR( "Detail level set to %+d\n", 22), Game_detail_level );
1178                         break;
1179
1180                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_DOWN:
1181                         Game_detail_level--;
1182                         HUD_printf( XSTR( "Detail level set to %+d\n", 22), Game_detail_level );
1183                         break;
1184
1185 #ifndef NDEBUG
1186                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_t:       {
1187                         extern int Test_begin;
1188
1189                         if ( Test_begin == 1 )
1190                                 break;
1191
1192                         Test_begin = 1;
1193                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Frame Rate test started", 23));
1194
1195                         break;
1196                 }
1197 #endif
1198                 case KEY_DEBUGGED + SDLK_d:
1199                         extern int OO_update_index;                     
1200
1201                         if(MULTIPLAYER_MASTER){
1202                                 do {
1203                                         OO_update_index++;
1204                                 } while((OO_update_index < (MAX_PLAYERS-1)) && !MULTI_CONNECTED(Net_players[OO_update_index]));
1205                                 if(OO_update_index >= MAX_PLAYERS-1){
1206                                         OO_update_index = -1;
1207                                 }                       
1208                         } else {
1209                                 if(OO_update_index < 0){
1210                                         OO_update_index = MY_NET_PLAYER_NUM;
1211                                 } else {
1212                                         OO_update_index = -1;
1213                                 }
1214                         }
1215                         break;
1216
1217                 // change player ship to next flyable type
1218                 case KEY_DEBUGGED + SDLK_RIGHT:
1219                         debug_cycle_player_ship(1);
1220                         break;
1221
1222                 // change player ship to previous flyable ship
1223                 case KEY_DEBUGGED + SDLK_LEFT:
1224                         debug_cycle_player_ship(-1);
1225                         break;
1226                 
1227                 // cycle target to ship
1228                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_RIGHT:
1229                         debug_cycle_targeted_ship(1);
1230                         break;
1231
1232                 // cycle target to previous ship
1233                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_LEFT:
1234                         debug_cycle_targeted_ship(-1);
1235                         break;
1236
1237                 // change species of the targeted ship
1238                 case KEY_DEBUGGED + SDLK_s: {
1239                         if ( Player_ai->target_objnum < 0 )
1240                                 break;
1241
1242                         object          *objp;
1243                         ship_info       *sip;
1244
1245                         objp = &Objects[Player_ai->target_objnum];
1246                         if ( objp->type != OBJ_SHIP )
1247                                 return;
1248
1249                         sip = &Ship_info[Ships[objp->instance].ship_info_index];
1250                         sip->species++;
1251                         if ( sip->species > SPECIES_SHIVAN )
1252                                 sip->species = 0;
1253
1254                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Species of target changed to: %s", 24), Species_names[sip->species]);
1255                         break;
1256                 }
1257                         
1258                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_s:
1259                         game_increase_skill_level();
1260                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Skill level set to %s.", 25), Skill_level_names(Game_skill_level));
1261                         break;
1262
1263 #ifndef MAKE_FS1
1264                 // kill all missiles
1265                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_1:
1266                         beam_test(1);
1267                         break;                          
1268                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_2:
1269                         beam_test(2);
1270                         break;          
1271                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_3:
1272                         beam_test(3);
1273                         break;                          
1274                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_4:
1275                         beam_test(4);
1276                         break;          
1277                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_5:
1278                         beam_test(5);
1279                         break;                          
1280                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_6:
1281                         beam_test(6);
1282                         break;          
1283                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_7:
1284                         beam_test(7);
1285                         break;                          
1286                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_8:
1287                         beam_test(8);
1288                         break;          
1289                 case KEY_DEBUGGED + KEY_SHIFTED + SDLK_9:
1290                         beam_test(9);
1291                         break;                          
1292
1293                 case KEY_DEBUGGED + KEY_CTRLED + SDLK_1:
1294                         beam_test_new(1);
1295                         break;                          
1296                 case KEY_DEBUGGED + KEY_CTRLED + SDLK_2:
1297                         beam_test_new(2);
1298                         break;          
1299                 case KEY_DEBUGGED + KEY_CTRLED + SDLK_3:
1300                         beam_test_new(3);
1301                         break;
1302 #endif
1303                                         
1304                 case KEY_DEBUGGED + SDLK_t: {
1305                         char buf[256];
1306                         event_music_get_info(buf, sizeof(buf));
1307                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, buf);
1308                         break;
1309                 }
1310
1311                 case KEY_DEBUGGED + SDLK_UP:
1312                         debug_change_song(1);
1313                         break;
1314
1315                 case KEY_DEBUGGED + SDLK_DOWN:
1316                         debug_change_song(-1);
1317                         break;
1318
1319 #ifndef MAKE_FS1
1320                 case SDLK_KP_MINUS: {
1321                         int init_flag = 0;
1322
1323                         if ( key_pressed(SDLK_1) )      {
1324                                 init_flag = 1;
1325                                 HUD_color_red -= 4;
1326                         } 
1327
1328                         if ( key_pressed(SDLK_2) )      {
1329                                 init_flag = 1;
1330                                 HUD_color_green -= 4;
1331                         } 
1332
1333                         if ( key_pressed(SDLK_3) )      {
1334                                 init_flag = 1;
1335                                 HUD_color_blue -= 4;
1336                         } 
1337
1338                         if (init_flag)
1339                                 HUD_init_colors();
1340
1341                         break;
1342                 }
1343 #endif
1344                 
1345                 case KEY_DEBUGGED + SDLK_y:
1346                         /*
1347                         // blast a debug lightning bolt in front of the player
1348                         vector start, strike;
1349                         
1350                         vm_vec_scale_add(&start, &Player_obj->pos, &Player_obj->orient.fvec, 300.0f);
1351                         vm_vec_scale_add2(&start, &Player_obj->orient.rvec, -300.0f);
1352                         vm_vec_scale_add(&strike, &start, &Player_obj->orient.rvec, 600.0f);
1353                         nebl_bolt(DEBUG_BOLT, &start, &strike);
1354                         */
1355                         extern int tst;
1356                         tst = 2;
1357                         break;
1358
1359 #ifndef MAKE_FS1
1360                 case SDLK_KP_PLUS: {
1361                         int init_flag = 0;
1362
1363                         if ( key_pressed(SDLK_1) )      {
1364                                 init_flag = 1;
1365                                 HUD_color_red += 4;
1366                         } 
1367
1368                         if ( key_pressed(SDLK_2) )      {
1369                                 init_flag = 1;
1370                                 HUD_color_green += 4;
1371                         } 
1372
1373                         if ( key_pressed(SDLK_3) )      {
1374                                 init_flag = 1;
1375                                 HUD_color_blue += 4;
1376                         } 
1377
1378                         if (init_flag)
1379                                 HUD_init_colors();
1380
1381                         break;
1382                 }
1383 #endif
1384         }       // end switch
1385
1386 }
1387 //#endif
1388
1389 void ppsk_hotkeys(int k)
1390 {
1391
1392 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
1393
1394         // use k to check for keys that can have Shift,Ctrl,Alt,Del status
1395         int hotkey_set;
1396
1397 #ifndef NDEBUG
1398         k &= ~KEY_DEBUGGED;                     // since hitting F11 will set this bit
1399 #endif
1400
1401         switch (k) {
1402                 case SDLK_F5:
1403                 case SDLK_F6:
1404                 case SDLK_F7:
1405                 case SDLK_F8:
1406                 case SDLK_F9:
1407                 case SDLK_F10:
1408                 case SDLK_F11:
1409                 case SDLK_F12:
1410                         hotkey_set = mission_hotkey_get_set_num(k);
1411                         if ( !(Players[Player_num].flags & PLAYER_FLAGS_MSG_MODE) )
1412                                 hud_target_hotkey_select( hotkey_set );
1413                         else
1414                                 hud_squadmsg_hotkey_select( hotkey_set );
1415
1416                         break;
1417
1418                 case SDLK_F5 + KEY_SHIFTED:
1419                 case SDLK_F6 + KEY_SHIFTED:
1420                 case SDLK_F7 + KEY_SHIFTED:
1421                 case SDLK_F8 + KEY_SHIFTED:
1422                 case SDLK_F9 + KEY_SHIFTED:
1423                 case SDLK_F10 + KEY_SHIFTED:
1424                 case SDLK_F11 + KEY_SHIFTED:
1425                 case SDLK_F12 + KEY_SHIFTED:
1426                         hotkey_set = mission_hotkey_get_set_num(k&(~KEY_SHIFTED));
1427                         mprintf(("Adding to set %d\n", hotkey_set+1));
1428                         if ( Player_ai->target_objnum == -1)
1429                                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "No target to add/remove from set %d.", 26), hotkey_set+1);
1430                         else  {
1431                                 hud_target_hotkey_add_remove( hotkey_set, &Objects[Player_ai->target_objnum], HOTKEY_USER_ADDED);
1432                                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "%s added to set %d. (F%d)", 27), Ships[Objects[Player_ai->target_objnum].instance].ship_name, hotkey_set, 4+hotkey_set+1);
1433                         }
1434
1435                         break;
1436
1437                 case SDLK_F5 + KEY_SHIFTED + KEY_ALTED:
1438                 case SDLK_F6 + KEY_SHIFTED + KEY_ALTED:
1439                 case SDLK_F7 + KEY_SHIFTED + KEY_ALTED:
1440                 case SDLK_F8 + KEY_SHIFTED + KEY_ALTED:
1441                 case SDLK_F9 + KEY_SHIFTED + KEY_ALTED:
1442                 case SDLK_F10 + KEY_SHIFTED + KEY_ALTED:
1443                 case SDLK_F11 + KEY_SHIFTED + KEY_ALTED:
1444                 case SDLK_F12 + KEY_SHIFTED + KEY_ALTED:
1445                         hotkey_set = mission_hotkey_get_set_num(k & ~(KEY_SHIFTED+KEY_ALTED));
1446                         hud_target_hotkey_clear( hotkey_set );
1447                         break;
1448
1449                 case KEY_SHIFTED + SDLK_MINUS:
1450                         if ( HUD_color_alpha > HUD_COLOR_ALPHA_USER_MIN )       {
1451                                 HUD_color_alpha--;
1452                                 HUD_init_colors();
1453                         }
1454                         break;
1455 /*              case KEY_SHIFTED + SDLK_u:
1456                         {
1457                         object *debris_create(object *source_obj, int model_num, int submodel_num, vector *pos, vector *exp_center, int hull_flag, float exp_force);
1458
1459                         object *temp = debris_create(Player_obj, Ships[0].modelnum, model_get(Ships[0].modelnum)->debris_objects[0], &Player_obj->pos, &Player_obj->pos, 1, 1.0f);
1460                         if (temp) {
1461                                 temp->hull_strength = 5000.0f;
1462                                 int objnum = temp - Objects;
1463                                 vm_vec_copy_scale(&Objects[objnum].phys_info.vel, &Player_obj->orient.fvec, 30.0f);
1464                         }
1465                         }
1466                         break;
1467 */
1468
1469                 case KEY_SHIFTED + SDLK_EQUALS:
1470                         if ( HUD_color_alpha < HUD_COLOR_ALPHA_USER_MAX ) {
1471                                 HUD_color_alpha++;
1472                                 HUD_init_colors();
1473                         }
1474                         break;
1475         }       // end switch
1476
1477 #endif
1478
1479 }
1480
1481 // check keypress 'key' against a set of valid controls and mark the match in the
1482 // player's button info bitfield.  Also checks joystick controls in the set.
1483 //
1484 // key = scancode (plus modifiers).
1485 // count = total size of the list
1486 // list = list of Control_config struct action indices to check for
1487 void process_set_of_keys(int key, int count, int *list)
1488 {
1489         int i;
1490
1491         for (i=0; i<count; i++)
1492                 if (check_control(list[i], key))
1493                         button_info_set(&Player->bi, list[i]);
1494 }
1495
1496 // routine to process keys used for player ship stuff (*not* ship movement).
1497 void process_player_ship_keys(int k)
1498 {
1499         int masked_k;
1500
1501         masked_k = k & ~KEY_CTRLED;     // take out CTRL modifier only  
1502
1503         // moved this line to beginning of function since hotkeys now encompass
1504         // F5 - F12.  We can return after using F11 as a hotkey.
1505         ppsk_hotkeys(masked_k);
1506         if (key_pressed(KEY_DEBUG_KEY)){
1507                 return;
1508         }
1509
1510         // if we're in supernova mode. do nothing
1511         if(Player->control_mode == PCM_SUPERNOVA){
1512                 return;
1513         }
1514
1515         // pass the key to the squadmate messaging code.  If the messaging code took the key, then return
1516         // from here immediately since we don't want to do further key processing.
1517         if ( hud_squadmsg_read_key(k) )
1518                 return;
1519
1520         if ( Player->control_mode == PCM_NORMAL )       {
1521                 //      The following things are not legal to do while dead.
1522                 if ( !(Game_mode & GM_DEAD) ) {
1523                         process_set_of_keys(masked_k, Normal_key_set_size, Normal_key_set);
1524                 } else  {
1525                         process_set_of_keys(masked_k, Dead_key_set_size, Dead_key_set);
1526                 }
1527         } else {
1528
1529         }
1530 }
1531
1532 // Handler for when player hits 'ESC' during the game
1533 void game_do_end_mission_popup()
1534 {
1535         int     pf_flags, choice;
1536 //      char    savegame_filename[_MAX_FNAME];
1537
1538         // do the multiplayer version of this
1539         if(Game_mode & GM_MULTIPLAYER){
1540                 multi_quit_game(PROMPT_ALL);
1541         } else {
1542
1543                 // single player version....
1544                 // do housekeeping things.
1545                 game_stop_time();
1546                 game_stop_looped_sounds();
1547                 snd_stop_all();
1548
1549                 pf_flags = PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON;
1550                 choice = popup(pf_flags, 3, POPUP_NO, XSTR( "&Yes, Quit", 28), XSTR( "Yes, &Restart", 29), XSTR( "Do you really want to end the mission?", 30));
1551
1552                 switch (choice) {
1553                 case 1:
1554                         // save the game before quitting if in campaign mode
1555                         // MWA -- 3/26/98 -- no more save/restore!!!!
1556 /*
1557                         if ( Game_mode & GM_CAMPAIGN_MODE ) {
1558                                 memset(savegame_filename, 0, _MAX_FNAME);
1559                                 mission_campaign_savefile_generate_root(savegame_filename);
1560                                 strcat(savegame_filename, NOX("svg"));
1561                                 if ( state_save_all(savegame_filename) ) {
1562                                         Int3(); // could not save this game
1563                                 }
1564                         }
1565 */
1566                         gameseq_post_event(GS_EVENT_END_GAME);
1567                         break;
1568
1569                 case 2:
1570                         gameseq_post_event(GS_EVENT_ENTER_GAME);
1571                         break;
1572
1573                 default:
1574                         break;  // do nothing
1575                 }
1576
1577                 game_start_time();
1578                 game_flush();
1579         }
1580 }
1581
1582 // handle pause keypress
1583 void game_process_pause_key()
1584 {
1585         // special processing for multiplayer
1586         if (Game_mode & GM_MULTIPLAYER) {                                                       
1587                 if(Multi_pause_status){
1588                         multi_pause_request(0);
1589                 } else {
1590                         multi_pause_request(1);
1591                 }               
1592         } else {
1593                 gameseq_post_event( GS_EVENT_PAUSE_GAME );
1594         }
1595 }
1596
1597 #define WITHIN_BBOX()   do { \
1598         float scale = 2.0f; \
1599         polymodel *pm = model_get(s_check->modelnum); \
1600         collided = 0; \
1601         if(pm != NULL){ \
1602                 vector temp = new_obj->pos; \
1603                 vector gpos; \
1604                 vm_vec_sub2(&temp, &hit_check->pos); \
1605                 vm_vec_rotate(&gpos, &temp, &hit_check->orient); \
1606                 if((gpos.xyz.x >= pm->mins.xyz.x * scale) && (gpos.xyz.y >= pm->mins.xyz.y * scale) && (gpos.xyz.z >= pm->mins.xyz.z * scale) && (gpos.xyz.x <= pm->maxs.xyz.x * scale) && (gpos.xyz.y <= pm->maxs.xyz.y * scale) && (gpos.xyz.z <= pm->maxs.xyz.z * scale)) { \
1607                         collided = 1; \
1608                 } \
1609         } \
1610 } while(0)
1611
1612 #define MOVE_AWAY_BBOX() do { \
1613         polymodel *pm = model_get(s_check->modelnum); \
1614         if(pm != NULL){ \
1615                 switch((int)frand_range(0.0f, 3.9f)){ \
1616                 case 0: \
1617                         new_obj->pos.xyz.x += 200.0f; \
1618                         break; \
1619                 case 1: \
1620                         new_obj->pos.xyz.x -= 200.0f; \
1621                         break; \
1622                 case 2: \
1623                         new_obj->pos.xyz.y += 200.0f; \
1624                         break; \
1625                 case 3: \
1626                         new_obj->pos.xyz.y -= 200.0f; \
1627                         break; \
1628                 default : \
1629                         new_obj->pos.xyz.z -= 200.0f; \
1630                         break; \
1631                 } \
1632         } \
1633 } while(0)
1634
1635 // process cheat codes
1636 void game_process_cheats(int k)
1637 {
1638         int i;
1639         char *cryptstring;
1640
1641         if ( k == 0 ){
1642                 return;
1643         }
1644
1645         // no cheats in multiplayer, ever
1646         if(Game_mode & GM_MULTIPLAYER){
1647                 Cheats_enabled = 0;
1648                 return;
1649         }
1650
1651         k = key_get_text_input();
1652
1653         if ( (k < 0) || (k > 255) ) {
1654                 return;
1655         }
1656
1657         for (i = 0; i < CHEAT_BUFFER_LEN; i++){
1658                 CheatBuffer[i]=CheatBuffer[i+1];
1659         }
1660
1661         CheatBuffer[CHEATSPOT]=(char)k;
1662
1663         cryptstring=jcrypt(&CheatBuffer[CHEAT_BUFFER_LEN - CRYPT_STRING_LENGTH]);               
1664
1665 #if defined(FS2_DEMO)
1666         if ( !strcmp(Cheat_code_demo, cryptstring) ) {
1667                 HUD_printf(XSTR( "Cheats enabled.", 31));
1668                 Cheats_enabled = 1;
1669                 if (Player->flags & PLAYER_FLAGS_MSG_MODE){
1670                         hud_squadmsg_toggle();
1671                 }
1672         }
1673         
1674 #else
1675
1676 #ifdef MAKE_FS1
1677         // two possible cheat codes for FS1, German and English
1678         if (Lcl_gr) {
1679                 if( !strcmp(Cheat_code_gr, cryptstring) && !(Game_mode & GM_MULTIPLAYER)){
1680                         Cheats_enabled = 1;
1681                         HUD_printf("Cheats enabled");
1682                 }
1683         } else {
1684                 if( !strcmp(Cheat_code, cryptstring) && !(Game_mode & GM_MULTIPLAYER)){
1685                         Cheats_enabled = 1;
1686                         HUD_printf("Cheats enabled");
1687                 }
1688         }
1689 #else
1690         if( !strcmp(Cheat_code, cryptstring) && !(Game_mode & GM_MULTIPLAYER)){
1691                 Cheats_enabled = 1;
1692                 HUD_printf("Cheats enabled");
1693         }
1694 #endif
1695
1696 #ifndef MAKE_FS1
1697         if( !strcmp(Cheat_code_fish, cryptstring) ){
1698                 // only enable in the main hall
1699                 if((gameseq_get_state() == GS_STATE_MAIN_MENU) && (main_hall_id() == 1)){
1700                         extern void fishtank_start();
1701                         fishtank_start();
1702                 }
1703         }
1704         if( !strcmp(Cheat_code_headz, cryptstring) ){
1705                 main_hall_vasudan_funny();
1706         }
1707         if( !strcmp(Cheat_code_skip, cryptstring) && (gameseq_get_state() == GS_STATE_MAIN_MENU)){
1708                 extern void main_hall_campaign_cheat();
1709                 main_hall_campaign_cheat();
1710         }
1711         if( !strcmp(Cheat_code_tooled, cryptstring) && (Game_mode & GM_IN_MISSION)){
1712                 Tool_enabled = 1;
1713                 HUD_printf("Prepare to be taken to school");
1714         }
1715         if( !strcmp(Cheat_code_pirate, cryptstring) && (Game_mode & GM_IN_MISSION) && (Player_obj != NULL)){
1716                 HUD_printf(NOX("Walk the plank"));
1717                 
1718                 for(int idx=0; idx<1; idx++){
1719                         vector add = Player_obj->pos;
1720                         add.xyz.x += frand_range(-700.0f, 700.0f);
1721                         add.xyz.y += frand_range(-700.0f, 700.0f);
1722                         add.xyz.z += frand_range(-700.0f, 700.0f);
1723
1724                         int objnum = ship_create(&vmd_identity_matrix, &add, Num_ship_types - 1);
1725
1726                         if(objnum >= 0){
1727                                 int collided;
1728                                 ship_obj *moveup;
1729                                 object *hit_check;
1730                                 ship *s_check;
1731                                 object *new_obj = &Objects[objnum];
1732
1733                                 // place him
1734                                 // now make sure we're not colliding with anyone                
1735                                 do {
1736                                         collided = 0;
1737                                         moveup = GET_FIRST(&Ship_obj_list);
1738                                         while(moveup!=END_OF_LIST(&Ship_obj_list)){
1739                                                 // don't check the new_obj itself!!
1740                                                 if(moveup->objnum != objnum){
1741                                                         hit_check = &Objects[moveup->objnum];
1742                                                         SDL_assert(hit_check->type == OBJ_SHIP);
1743                                                         SDL_assert(hit_check->instance >= 0);
1744                                                         if((hit_check->type != OBJ_SHIP) || (hit_check->instance < 0)){
1745                                                                 continue;
1746                                                         }
1747                                                         s_check = &Ships[hit_check->instance];
1748                                                         
1749                                                         // just to make sure we don't get any strange magnitude errors
1750                                                         if(vm_vec_same(&hit_check->pos, &Objects[objnum].pos)){
1751                                                                 Objects[objnum].pos.xyz.x += 1.0f;
1752                                                         }
1753                                                         
1754                                                         WITHIN_BBOX();                          
1755                                                         if(collided){                                           
1756                                                                 MOVE_AWAY_BBOX();
1757                                                                 break;
1758                                                         } 
1759                                                         collided = 0;
1760                                                 }
1761                                                 moveup = GET_NEXT(moveup);
1762                                         }
1763                                 } while(collided);                                      
1764                         
1765                                 // warpin
1766                                 shipfx_warpin_start(&Objects[objnum]);
1767
1768                                 // tell him to attack                           
1769                                 // ai_add_ship_goal_player( AIG_TYPE_PLAYER_SHIP, AI_GOAL_CHASE_ANY, SM_ATTACK, NULL, &Ai_info[Ships[Objects[objnum].instance].ai_index] );
1770                         }
1771                 }
1772         }
1773 #endif  // !MAKE_FS1
1774 #endif
1775
1776 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
1777         if ( !strcmp(Cheat_code_movies, cryptstring) ) {
1778                 HUD_printf(XSTR( "All movies available in Tech Room", 32));
1779                 All_movies_enabled = 1;
1780                 if (Player->flags & PLAYER_FLAGS_MSG_MODE){
1781                         hud_squadmsg_toggle();
1782                 }
1783         }
1784 #endif
1785
1786 /*
1787 //#ifdef INTERPLAYQA
1788         if ( !strcmp(Cheat_code_in_game, cryptstring) ) {
1789                 HUD_printf(XSTR( "Cheats enabled.", 31));
1790                 Cheats_enabled = 1;
1791                 if (Player->flags & PLAYER_FLAGS_MSG_MODE){
1792                         hud_squadmsg_toggle();
1793                 }
1794         } else if ( !strcmp(Cheat_code_movies, cryptstring) ) {
1795                 HUD_printf(XSTR( "All movies available in Tech Room", 32));
1796                 All_movies_enabled = 1;
1797                 if (Player->flags & PLAYER_FLAGS_MSG_MODE){
1798                         hud_squadmsg_toggle();
1799                 }
1800         } else if( !strcmp(Cheat_code_pirate, cryptstring) ){
1801                 HUD_printf(NOX("Walk the plank"));
1802                 
1803                 for(int idx=0; idx<1; idx++){
1804                         vector add;
1805                         add.x = frand_range(-1000.0f, 1000.0f);
1806                         add.y = frand_range(-1000.0f, 1000.0f);
1807                         add.z = frand_range(-1000.0f, 1000.0f);
1808
1809                         int objnum = ship_create(&vmd_identity_matrix, &add, Num_ship_types - 1);                       
1810
1811                         if(objnum >= 0){
1812                                 shipfx_warpin_start(&Objects[objnum]);
1813                         }
1814                 }
1815         }
1816 #endif
1817         */
1818 }
1819
1820 void game_process_keys()
1821 {
1822         int k;
1823
1824         button_info_clear(&Player->bi); // clear out the button info struct for the player
1825    do {
1826                 k = game_poll();                
1827         
1828                 // AL 12-10-97: Scan for keys used to leave the dead state      (don't process any)
1829                 // DB 1-13-98 : New popup code will run the game do state, so we must skip 
1830                 //              all key processing in this function, since everything should be run through the popup dialog
1831                 if ( Game_mode & GM_DEAD_BLEW_UP ) {
1832                         continue;
1833                 }
1834
1835                 game_process_cheats( k );
1836
1837                 // mwa -- 4/5/97 Moved these two function calls before the switch statement.  I don't think
1838                 // that this has adverse affect on anything and is acutally desireable because of the
1839                 // ESC key being used to quit any HUD message/input mode that might be currently in use
1840                 process_player_ship_keys(k);
1841
1842 //              #ifndef NDEBUG
1843                 process_debug_keys(k);          //      Note, also processed for cheats.
1844 //              #endif          
1845
1846                 switch (k) {
1847                         case 0:
1848                                 // No key
1849                                 break;
1850                         
1851                         case SDLK_ESCAPE:
1852                                 if ( Player->control_mode != PCM_NORMAL )       {
1853                                         if ( Player->control_mode == PCM_WARPOUT_STAGE1 )       {
1854                                                 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
1855                                         } else {
1856                                                 // too late to abort warp out!
1857                                         }
1858                                 } else {
1859                                         // let the ESC key break out of messaging mode
1860                                         if ( Players[Player_num].flags & PLAYER_FLAGS_MSG_MODE ) {
1861                                                 hud_squadmsg_toggle();
1862                                                 break;
1863                                         }
1864
1865                                         // if in external view or chase view, go back to cockpit view
1866                                         if ( Viewer_mode & (VM_EXTERNAL|VM_CHASE|VM_OTHER_SHIP) ) {
1867                                                 Viewer_mode &= ~(VM_EXTERNAL|VM_CHASE|VM_OTHER_SHIP);
1868                                                 break;
1869                                         }
1870
1871                                         if (!(Game_mode & GM_DEAD_DIED))
1872                                                 game_do_end_mission_popup();
1873
1874                                 }
1875                                 break;
1876
1877                         case SDLK_y:
1878                                 break;
1879
1880                         case SDLK_n:
1881                                 break;                  
1882
1883                         case KEY_ALTED + KEY_SHIFTED+SDLK_j:
1884                                 // treat the current joystick position as the center position
1885                                 joy_set_cen();
1886                                 break;
1887
1888                         case KEY_DEBUGGED | SDLK_PAUSE:
1889                                 gameseq_post_event( GS_EVENT_DEBUG_PAUSE_GAME );
1890                                 break;
1891
1892                         case SDLK_PAUSE:
1893                                 game_process_pause_key();
1894                                 break;
1895                 } // end switch
1896         } while (k);
1897
1898         button_info_do(&Player->bi);    // call functions based on status of button_info bit vectors
1899 }
1900
1901 int button_function_critical(int n, net_player *p = NULL)
1902 {
1903         object *objp;
1904         player *pl;
1905         net_player *npl;
1906         int at_self;    // flag indicating the object is local (for hud messages, etc)
1907
1908         SDL_assert(n >= 0);
1909    
1910         // multiplayer clients should leave critical button bits alone and pass them to the server instead
1911         if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)) {
1912                 // if this flag is set, we should apply the button itself (came from the server)
1913                 if (!Multi_button_info_ok){
1914                         return 0;
1915                 }
1916         }
1917
1918         // in single player mode make sure we're using the player object and the player himself, otherwise use the object and
1919         // player pertaining to the passed net_player
1920         npl = NULL;
1921         if (p == NULL) {
1922                 objp = Player_obj;
1923                 pl = Player;
1924                 if(Game_mode & GM_MULTIPLAYER){
1925                         npl = Net_player;
1926
1927                         // if we're the server in multiplayer and we're an observer, don't process our own critical button functions
1928                         if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
1929                                 return 0;
1930                         }
1931                 }
1932                 at_self = 1;
1933         } else {
1934                 objp = &Objects[p->player->objnum];
1935                 pl = p->player;
1936                 npl = p;
1937                 at_self = 0;
1938
1939                 if ( NETPLAYER_IS_DEAD(npl) || (Ships[Objects[pl->objnum].instance].flags & SF_DYING) )
1940                         return 0;
1941         }
1942         
1943         switch (n) {                            
1944                 // cycle to next secondary weapon
1945                 case CYCLE_SECONDARY:
1946                         if(at_self)
1947                                 control_used(CYCLE_SECONDARY);
1948                         
1949                         hud_gauge_popup_start(HUD_WEAPONS_GAUGE);
1950                         if (ship_select_next_secondary(objp)) {
1951                                 ship* shipp = &Ships[objp->instance];
1952                                 if ( timestamp_elapsed(shipp->weapons.next_secondary_fire_stamp[shipp->weapons.current_secondary_bank]) ) {
1953                                         shipp->weapons.next_secondary_fire_stamp[shipp->weapons.current_secondary_bank] = timestamp(250);       //      1/4 second delay until can fire
1954                                 }
1955
1956                                 // multiplayer server should maintain bank/link status here
1957                                 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
1958                                         SDL_assert(npl != NULL);
1959                                         multi_server_update_player_weapons(npl,shipp);                                                                          
1960                                 }                                       
1961                         }                       
1962                         break;
1963
1964                 // cycle number of missiles
1965                 case CYCLE_NUM_MISSLES:
1966                         if(at_self)
1967                                 control_used(CYCLE_NUM_MISSLES);
1968
1969                         if ( objp == Player_obj ) {
1970                                 if ( Player_ship->weapons.num_secondary_banks <= 0 ) {
1971                                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "This ship has no secondary weapons", 33));
1972                                         gamesnd_play_iface(SND_GENERAL_FAIL);
1973                                         break;
1974                                 }
1975                         }
1976                                         
1977                         if ( Ships[objp->instance].flags & SF_SECONDARY_DUAL_FIRE ) {           
1978                                 Ships[objp->instance].flags &= ~SF_SECONDARY_DUAL_FIRE;
1979                                 if(at_self) {
1980                                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary weapon set to normal fire mode", 34));
1981                                         snd_play( &Snds[SND_SECONDARY_CYCLE] );
1982                                         hud_gauge_popup_start(HUD_WEAPONS_GAUGE);
1983                                 }
1984                         } else {
1985                                 Ships[objp->instance].flags |= SF_SECONDARY_DUAL_FIRE;
1986                                 if(at_self) {
1987                                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary weapon set to dual fire mode", 35));
1988                                         snd_play( &Snds[SND_SECONDARY_CYCLE] );
1989                                         hud_gauge_popup_start(HUD_WEAPONS_GAUGE);
1990                                 }
1991                         }
1992
1993                         // multiplayer server should maintain bank/link status here
1994                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
1995                                 SDL_assert(npl != NULL);
1996                                 multi_server_update_player_weapons(npl,&Ships[objp->instance]);                                                                         
1997                         }                                       
1998                         break;
1999
2000                 // increase weapon recharge rate
2001                 case INCREASE_WEAPON:
2002                         if(at_self)
2003                                 control_used(INCREASE_WEAPON);
2004                         increase_recharge_rate(objp, WEAPONS);
2005
2006                         // multiplayer server should maintain bank/link status here
2007                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
2008                                 SDL_assert(npl != NULL);
2009                                 multi_server_update_player_weapons(npl,&Ships[objp->instance]);                                                                         
2010                         }                                       
2011                         break;
2012
2013                 // decrease weapon recharge rate
2014                 case DECREASE_WEAPON:
2015                         if(at_self)
2016                                 control_used(DECREASE_WEAPON);
2017                         decrease_recharge_rate(objp, WEAPONS);
2018
2019                         // multiplayer server should maintain bank/link status here
2020                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
2021                                 SDL_assert(npl != NULL);
2022                                 multi_server_update_player_weapons(npl,&Ships[objp->instance]);                                                                         
2023                         }                                                               
2024                         break;
2025
2026                 // increase shield recharge rate
2027                 case INCREASE_SHIELD:
2028                         if(at_self)
2029                                 control_used(INCREASE_SHIELD);
2030                         increase_recharge_rate(objp, SHIELDS);
2031
2032                         // multiplayer server should maintain bank/link status here
2033                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
2034                                 SDL_assert(npl != NULL);
2035                                 multi_server_update_player_weapons(npl,&Ships[objp->instance]);                                                                         
2036                         }                                                               
2037                         break;
2038
2039                 // decrease shield recharge rate
2040                 case DECREASE_SHIELD:
2041                         if(at_self)
2042                                 control_used(DECREASE_SHIELD);
2043                         decrease_recharge_rate(objp, SHIELDS);
2044
2045                         // multiplayer server should maintain bank/link status here
2046                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
2047                                 SDL_assert(npl != NULL);
2048                                 multi_server_update_player_weapons(npl,&Ships[objp->instance]);                                                                         
2049                         }                                                               
2050                         break;
2051
2052                 // increase energy to engines
2053                 case INCREASE_ENGINE:
2054                         if(at_self)
2055                                 control_used(INCREASE_ENGINE);
2056                         increase_recharge_rate(objp, ENGINES);
2057
2058                         // multiplayer server should maintain bank/link status here
2059                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
2060                                 SDL_assert(npl != NULL);
2061                                 multi_server_update_player_weapons(npl,&Ships[objp->instance]);                                                                         
2062                         }                                                       
2063                         break;
2064
2065                 // decrease energy to engines
2066                 case DECREASE_ENGINE:
2067                         if(at_self)
2068                         control_used(DECREASE_ENGINE);
2069                         decrease_recharge_rate(objp, ENGINES);
2070
2071                         // multiplayer server should maintain bank/link status here
2072                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
2073                                 SDL_assert(npl != NULL);
2074                                 multi_server_update_player_weapons(npl,&Ships[objp->instance]);                                                                         
2075                         }                                                                               
2076                         break;
2077
2078                 // equalize recharge rates
2079                 case ETS_EQUALIZE:
2080                         if (at_self) {
2081                         control_used(ETS_EQUALIZE);
2082                         }
2083
2084                         set_default_recharge_rates(objp);
2085                         snd_play( &Snds[SND_ENERGY_TRANS] );
2086                         // multiplayer server should maintain bank/link status here
2087                         if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
2088                                 SDL_assert(npl != NULL);
2089                                 multi_server_update_player_weapons(npl,&Ships[objp->instance]);                                                                         
2090                         }                                                                               
2091                         break;
2092
2093                 // equalize shield energy to all quadrants
2094                 case SHIELD_EQUALIZE:
2095                         if(at_self){
2096                                 control_used(SHIELD_EQUALIZE);
2097                         }
2098                         hud_shield_equalize(objp, pl);
2099                         break;
2100
2101                 // transfer shield energy to front
2102                 case SHIELD_XFER_TOP:
2103                         if(at_self){
2104                         control_used(SHIELD_XFER_TOP);
2105                         }
2106                         hud_augment_shield_quadrant(objp, 1);
2107                         break;
2108
2109                 // transfer shield energy to rear
2110                 case SHIELD_XFER_BOTTOM:
2111                         if(at_self)
2112                                 control_used(SHIELD_XFER_BOTTOM);
2113                         hud_augment_shield_quadrant(objp, 2);
2114                         break;
2115
2116                 // transfer shield energy to left
2117                 case SHIELD_XFER_LEFT:
2118                         if(at_self)
2119                                 control_used(SHIELD_XFER_LEFT);
2120                         hud_augment_shield_quadrant(objp, 3);
2121                         break;
2122                         
2123                 // transfer shield energy to right
2124                 case SHIELD_XFER_RIGHT:
2125                         if(at_self)
2126                                 control_used(SHIELD_XFER_RIGHT);
2127                         hud_augment_shield_quadrant(objp, 0);
2128                         break;
2129
2130                 // transfer energy to shield from weapons
2131                 case XFER_SHIELD:
2132                         if(at_self)
2133                                 control_used(XFER_SHIELD);
2134                         transfer_energy_to_shields(objp);
2135                         break;
2136
2137                 // transfer energy to weapons from shield
2138                 case XFER_LASER:
2139                         if(at_self)
2140                                 control_used(XFER_LASER);
2141                         transfer_energy_to_weapons(objp);
2142                         break;
2143
2144                 // following are not handled here, but we need to bypass the Int3()
2145                 case LAUNCH_COUNTERMEASURE:
2146                 case VIEW_SLEW:
2147                 case VIEW_EXTERNAL:
2148                 case VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK:
2149                 case ONE_THIRD_THROTTLE:
2150                 case TWO_THIRDS_THROTTLE:
2151                 case MINUS_5_PERCENT_THROTTLE:
2152                 case PLUS_5_PERCENT_THROTTLE:
2153                 case ZERO_THROTTLE:
2154                 case MAX_THROTTLE:
2155                         return 0;
2156
2157                 default :
2158                         Int3(); // bad bad bad
2159                         break;
2160         }
2161
2162         return 1;
2163 }
2164
2165 // return !0 if the action is allowed, otherwise return 0
2166 int button_allowed(int n)
2167 {
2168         if ( hud_disabled() ) {
2169                 switch (n) {
2170                 case SHOW_GOALS:
2171                 case END_MISSION:
2172                 case CYCLE_NEXT_PRIMARY:
2173                 case CYCLE_PREV_PRIMARY:
2174                 case CYCLE_SECONDARY:
2175                 case ONE_THIRD_THROTTLE:
2176                 case TWO_THIRDS_THROTTLE:
2177                 case PLUS_5_PERCENT_THROTTLE:
2178                 case MINUS_5_PERCENT_THROTTLE:
2179                 case ZERO_THROTTLE:
2180                 case MAX_THROTTLE:
2181                         return 1;
2182                 default:
2183                         return 0;
2184                 }
2185         }
2186
2187         return 1;
2188 }
2189
2190 // execute function corresponding to action n
2191 // basically, these are actions which don't affect demo playback at all
2192 int button_function_demo_valid(int n)
2193 {
2194         // by default, we'll return "not processed". ret will get set to 1, if this is one of the keys which is always allowed, even in demo
2195         // playback.
2196         int ret = 0;
2197
2198         //      No keys, not even targeting keys, when player in death roll.  He can press keys after he blows up.
2199         if (Game_mode & GM_DEAD_DIED){
2200                 return 0;
2201         }
2202
2203         // any of these buttons are valid
2204         switch(n){
2205         case VIEW_CHASE:
2206                 control_used(VIEW_CHASE);
2207                 Viewer_mode ^= VM_CHASE;
2208                 if ( Viewer_mode & VM_CHASE ) {
2209                         Viewer_mode &= ~VM_EXTERNAL;
2210                 }
2211                 ret = 1;
2212                 break;
2213
2214         case VIEW_EXTERNAL:
2215                 control_used(VIEW_EXTERNAL);
2216                 Viewer_mode ^= VM_EXTERNAL;
2217                 Viewer_mode &= ~VM_EXTERNAL_CAMERA_LOCKED;      // reset camera lock when leave/entering external view
2218                 if ( Viewer_mode & VM_EXTERNAL ) {
2219                         Viewer_mode &= ~VM_CHASE;
2220                 }
2221                 ret = 1;
2222                 break;
2223
2224         case VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK:
2225                 control_used(VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK);
2226                 if ( Viewer_mode & VM_EXTERNAL ) {
2227                 Viewer_mode ^= VM_EXTERNAL_CAMERA_LOCKED;
2228                 if ( Viewer_mode & VM_EXTERNAL_CAMERA_LOCKED ) {
2229                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "External camera is locked, controls will move ship", 36));
2230                         } else {
2231                                 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "External camera is free, controls will move the camera, not the ship", 37));
2232                         }
2233                 }
2234                 ret = 1;
2235                 break;
2236
2237         case VIEW_OTHER_SHIP:
2238                 control_used(VIEW_OTHER_SHIP);
2239                 if ( Player_ai->target_objnum < 0 ) {
2240                         snd_play( &Snds[SND_TARGET_FAIL] );
2241                 } else {
2242                         if ( Objects[Player_ai->target_objnum].type != OBJ_SHIP )  {
2243                                 snd_play( &Snds[SND_TARGET_FAIL] );
2244                         } else {
2245                                 Viewer_mode ^= VM_OTHER_SHIP;
2246                         }
2247                 }
2248                 ret = 1;
2249                 break;
2250
2251         case TIME_SLOW_DOWN:
2252                 if ( Game_mode & GM_NORMAL ) {
2253                         if ( Game_time_compression > F1_0) {
2254                                 Game_time_compression /= 2;
2255                         } else {
2256                                 gamesnd_play_error_beep();
2257                         }
2258                 } else {
2259                         gamesnd_play_error_beep();
2260                 }
2261                 ret = 1;
2262                 break;
2263
2264         case TIME_SPEED_UP:
2265                 if ( Game_mode & GM_NORMAL ) {
2266                         if ( Game_time_compression < (F1_0*4) ) {
2267                                 Game_time_compression *= 2;
2268                         } else {
2269                                 gamesnd_play_error_beep();
2270                         }
2271                 } else {
2272                         gamesnd_play_error_beep();
2273                 }
2274                 ret = 1;
2275                 break;
2276         }
2277
2278         // done
2279         return ret;
2280 }
2281
2282 // execute function corresponding to action n (BUTTON_ #define from KeyControl.h)
2283 int button_function(int n)
2284 {
2285         SDL_assert(n >= 0);
2286
2287         if ( !button_allowed(n) ) {
2288                 return 0;
2289         }
2290
2291         //      No keys, not even targeting keys, when player in death roll.  He can press keys after he blows up.
2292         if (Game_mode & GM_DEAD_DIED){
2293                 return 0;
2294         }
2295                 
2296         switch (n) {
2297                 // cycle to next primary weapon
2298                 case CYCLE_NEXT_PRIMARY:                        
2299                         // bogus?
2300                         if((Player_obj == NULL) || (Player_ship == NULL)){
2301                                 break;
2302                         }
2303
2304                         hud_gauge_popup_start(HUD_WEAPONS_GAUGE);
2305                         if (ship_select_next_primary(Player_obj, CYCLE_PRIMARY_NEXT)) {
2306                                 ship* shipp = Player_ship;
2307                                 shipp->weapons.next_primary_fire_stamp[shipp->weapons.current_primary_bank] = timestamp(250);   //      1/4 second delay until can fire                         
2308                                 // multiplayer server should maintain bank/link status here
2309                                 // if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
2310 //                                      SDL_assert(npl != NULL);
2311 //                                      multi_server_update_player_weapons(npl,shipp);                                                                          
2312 //                              }                                       
2313                         }                       
2314                         break;
2315
2316                 // cycle to previous primary weapon
2317                 case CYCLE_PREV_PRIMARY:                        
2318                         // bogus?
2319                         if((Player_obj == NULL) || (Player_ship == NULL)){
2320                                 break;
2321                         }
2322
2323                         hud_gauge_popup_start(HUD_WEAPONS_GAUGE);
2324                         if (ship_select_next_primary(Player_obj, CYCLE_PRIMARY_PREV)) {
2325                                 ship* shipp = Player_ship;
2326                                 shipp->weapons.next_primary_fire_stamp[shipp->weapons.current_primary_bank] = timestamp(250);   //      1/4 second delay until can fire
2327
2328                                 // multiplayer server should maintain bank/link status here
2329                                 // if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
2330                                         // SDL_assert(npl != NULL);
2331                                         // multi_server_update_player_weapons(npl,shipp);                                                                               
2332                                 // }                                    
2333                         }                       
2334                         break;
2335
2336                 // cycle to next secondary weapon
2337                 case CYCLE_SECONDARY:
2338                         return button_function_critical(CYCLE_SECONDARY);
2339                         break;
2340
2341                 // cycle number of missiles fired from secondary bank
2342                 case CYCLE_NUM_MISSLES:
2343          return button_function_critical(CYCLE_NUM_MISSLES);                    
2344                         break;
2345
2346                 // undefined in multiplayer for clients right now
2347                 // match target speed
2348                 case MATCH_TARGET_SPEED:                        
2349                         control_used(MATCH_TARGET_SPEED);
2350                         // If player is auto-matching, break auto-match speed
2351                         if ( Player->flags & PLAYER_FLAGS_AUTO_MATCH_SPEED ) {
2352                                 Player->flags &= ~PLAYER_FLAGS_AUTO_MATCH_SPEED;
2353                         }
2354                         player_match_target_speed();                                            
2355                         break;
2356
2357                 // undefined in multiplayer for clients right now
2358                 // toggle auto-match target speed
2359                 case TOGGLE_AUTO_MATCH_TARGET_SPEED:
2360                         // multiplayer observers can't match target speed
2361                         if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && ((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)) ){
2362                                 break;
2363                         }
2364         
2365                         Player->flags ^= PLAYER_FLAGS_AUTO_MATCH_SPEED;                 
2366                         control_used(TOGGLE_AUTO_MATCH_TARGET_SPEED);
2367                         hud_gauge_popup_start(HUD_AUTO_SPEED);
2368                         if ( Players[Player_num].flags & PLAYER_FLAGS_AUTO_MATCH_SPEED ) {
2369                                 snd_play(&Snds[SND_SHIELD_XFER_OK], 1.0f);
2370 //                              HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Auto match target speed activated", -1));
2371                                 if ( !Player->flags & PLAYER_FLAGS_MATCH_TARGET ) {
2372                                         player_match_target_speed();
2373                                 }
2374                         }
2375                         else {
2376 //                              HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Auto match target deactivated", -1));
2377                                 snd_play(&Snds[SND_SHIELD_XFER_OK], 1.0f);
2378                                 player_match_target_speed();
2379                         }                       
2380                         break;
2381
2382                 // target next
2383                 case TARGET_NEXT:
2384                         control_used(TARGET_NEXT);                      
2385                         if ( hud_sensors_ok(Player_ship) ) {
2386                                 hud_target_next();
2387                         }
2388                         break;
2389
2390                 // target previous
2391                 case TARGET_PREV:
2392                         control_used(TARGET_PREV);                      
2393                         if ( hud_sensors_ok(Player_ship) ) {
2394                                 hud_target_prev();                      
2395                         }
2396                         break;
2397
2398                 // target the next hostile target
2399                 case TARGET_NEXT_CLOSEST_HOSTILE:
2400                         control_used(TARGET_NEXT_CLOSEST_HOSTILE);                      
2401                         if (hud_sensors_ok(Player_ship)){
2402                                 hud_target_next_list();
2403                         }                       
2404                         break;
2405
2406                 // target the previous closest hostile 
2407                 case TARGET_PREV_CLOSEST_HOSTILE:
2408                         control_used(TARGET_PREV_CLOSEST_HOSTILE);                      
2409                         if (hud_sensors_ok(Player_ship)){
2410                                 hud_target_next_list(1,0);
2411                         }
2412                         break;
2413
2414                 // toggle auto-targeting
2415                 case TOGGLE_AUTO_TARGETING:
2416                         control_used(TOGGLE_AUTO_TARGETING);
2417                         hud_gauge_popup_start(HUD_AUTO_TARGET);
2418                         Players[Player_num].flags ^= PLAYER_FLAGS_AUTO_TARGETING;
2419                         if ( Players[Player_num].flags & PLAYER_FLAGS_AUTO_TARGETING ) {
2420                                 if (hud_sensors_ok(Player_ship)) {
2421                                         hud_target_closest(opposing_team_mask(Player_ship->team), -1, FALSE, TRUE );
2422                                         snd_play(&Snds[SND_SHIELD_XFER_OK], 1.0f);
2423 //                                      HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Auto targeting activated", -1));
2424                                 } else {
2425                                         Players[Player_num].flags ^= PLAYER_FLAGS_AUTO_TARGETING;
2426                                 }
2427                         } else {
2428                                 snd_play(&Snds[SND_SHIELD_XFER_OK], 1.0f);
2429 //                              HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Auto targeting deactivated", -1));
2430                         }
2431                         break;
2432
2433                 // target the next friendly ship
2434                 case TARGET_NEXT_CLOSEST_FRIENDLY:
2435                         control_used(TARGET_NEXT_CLOSEST_FRIENDLY);                     
2436                         if (hud_sensors_ok(Player_ship)){
2437                                 hud_target_next_list(0);
2438                         }
2439                         break;
2440
2441                 // target the closest friendly ship
2442                 case TARGET_PREV_CLOSEST_FRIENDLY:
2443                         control_used(TARGET_PREV_CLOSEST_FRIENDLY);                     
2444                         if (hud_sensors_ok(Player_ship)) {
2445                                 hud_target_next_list(0,0);
2446                         }
2447                         break;
2448
2449                 // target ship closest to center of reticle
2450                 case TARGET_SHIP_IN_RETICLE:
2451                         control_used(TARGET_SHIP_IN_RETICLE);                   
2452                         if (hud_sensors_ok(Player_ship)){
2453                                 hud_target_in_reticle_new();
2454                         }
2455                         break;
2456
2457                 case TARGET_LAST_TRANMISSION_SENDER:
2458                         control_used(TARGET_LAST_TRANMISSION_SENDER);
2459                         if ( hud_sensors_ok(Player_ship)) {
2460                                 hud_target_last_transmit();
2461                         }
2462                         break;
2463
2464                 // target the closest repair ship
2465                 case TARGET_CLOSEST_REPAIR_SHIP:
2466                         control_used(TARGET_CLOSEST_REPAIR_SHIP);
2467                         // AL: Try to find the closest repair ship coming to repair the player... if no support
2468                         //               ships are coming to rearm the player, just try for the closest repair ship
2469                         if ( hud_target_closest_repair_ship(OBJ_INDEX(Player_obj)) == 0 ) {
2470                                 if ( hud_target_closest_repair_ship() == 0 ) {
2471                                         snd_play(&Snds[SND_TARGET_FAIL]);
2472                                 }
2473                         }
2474                         break;
2475
2476                 // target the closest ship attacking current target
2477                 case TARGET_CLOSEST_SHIP_ATTACKING_TARGET:
2478                         control_used(TARGET_CLOSEST_SHIP_ATTACKING_TARGET);
2479                         if (hud_sensors_ok(Player_ship)){
2480                                 hud_target_closest(opposing_team_mask(Player_ship->team), Player_ai->target_objnum);
2481                         }
2482                         break;
2483
2484                 // stop targeting ship
2485                 case STOP_TARGETING_SHIP:
2486                         control_used(STOP_TARGETING_SHIP);
2487                         hud_cease_targeting();
2488                         break;
2489
2490                 // target closest ship that is attacking player
2491                 case TARGET_CLOSEST_SHIP_ATTACKING_SELF:
2492                         control_used(TARGET_CLOSEST_SHIP_ATTACKING_SELF);
2493                         if (hud_sensors_ok(Player_ship)){
2494                                 hud_target_closest(opposing_team_mask(Player_ship->team), OBJ_INDEX(Player_obj), TRUE, 0, 1);
2495                         }
2496                         break;
2497
2498                 // target your target's target
2499                 case TARGET_TARGETS_TARGET:
2500                         control_used(TARGET_TARGETS_TARGET);
2501                         if (hud_sensors_ok(Player_ship)){
2502                                 hud_target_targets_target();
2503                         }
2504                         break;
2505
2506                 // target ships subsystem in reticle
2507                 case TARGET_SUBOBJECT_IN_RETICLE:
2508                         control_used(TARGET_SUBOBJECT_IN_RETICLE);
2509                         if (hud_sensors_ok(Player_ship)){
2510                                 hud_target_subsystem_in_reticle();
2511                         }
2512                         break;
2513
2514                 case TARGET_PREV_SUBOBJECT:
2515                         control_used(TARGET_PREV_SUBOBJECT);
2516                         if (hud_sensors_ok(Player_ship)){
2517                                 hud_target_prev_subobject();
2518                         }
2519                         break;
2520
2521                 // target next subsystem on current target
2522                 case TARGET_NEXT_SUBOBJECT:
2523                         control_used(TARGET_NEXT_SUBOBJECT);
2524                         if (hud_sensors_ok(Player_ship)){
2525                                 hud_target_next_subobject();
2526                         }
2527                         break;
2528
2529                 // stop targeting subsystems on ship
2530                 case STOP_TARGETING_SUBSYSTEM:
2531                         control_used(STOP_TARGETING_SUBSYSTEM);
2532                         hud_cease_subsystem_targeting();
2533                         break;
2534                         
2535                 case TARGET_NEXT_BOMB:
2536                         control_used(TARGET_NEXT_BOMB);
2537                         hud_target_missile(Player_obj, 1);
2538                         break;
2539
2540                 case TARGET_PREV_BOMB:
2541                         control_used(TARGET_PREV_BOMB);
2542                         hud_target_missile(Player_obj, 0);
2543                         break;
2544
2545                 case TARGET_NEXT_UNINSPECTED_CARGO:
2546                         hud_target_uninspected_object(1);
2547                         break;
2548
2549                 case TARGET_PREV_UNINSPECTED_CARGO:
2550                         hud_target_uninspected_object(0);
2551                         break;
2552
2553                 case TARGET_NEWEST_SHIP:
2554                         hud_target_newest_ship();
2555                         break;
2556
2557                 case TARGET_NEXT_LIVE_TURRET:
2558                         hud_target_live_turret(1);
2559                         break;
2560
2561                 case TARGET_PREV_LIVE_TURRET:
2562                         hud_target_live_turret(0);
2563                         break;
2564
2565                 // wingman message: attack current target
2566                 case ATTACK_MESSAGE:
2567                         control_used(ATTACK_MESSAGE);
2568                         hud_squadmsg_shortcut( ATTACK_TARGET_ITEM );
2569                         break;
2570
2571                 // wingman message: disarm current target
2572                 case DISARM_MESSAGE:
2573                         control_used(DISARM_MESSAGE);
2574                         hud_squadmsg_shortcut( DISARM_TARGET_ITEM );
2575                         break;
2576
2577                 // wingman message: disable current target
2578                 case DISABLE_MESSAGE:
2579                         control_used(DISABLE_MESSAGE);
2580                         hud_squadmsg_shortcut( DISABLE_TARGET_ITEM );
2581                         break;
2582
2583                 // wingman message: disable current target
2584                 case ATTACK_SUBSYSTEM_MESSAGE:
2585                         control_used(ATTACK_SUBSYSTEM_MESSAGE);
2586                         hud_squadmsg_shortcut( DISABLE_SUBSYSTEM_ITEM );
2587                         break;
2588
2589                 // wingman message: capture current target
2590                 case CAPTURE_MESSAGE:
2591                         control_used(CAPTURE_MESSAGE);
2592                         hud_squadmsg_shortcut( CAPTURE_TARGET_ITEM );
2593                         break;
2594
2595                 // wingman message: engage enemy
2596                 case ENGAGE_MESSAGE:
2597                 control_used(ENGAGE_MESSAGE);
2598                         hud_squadmsg_shortcut( ENGAGE_ENEMY_ITEM );
2599                         break;
2600
2601                 // wingman message: form on my wing
2602                 case FORM_MESSAGE:
2603                         control_used(FORM_MESSAGE);
2604                         hud_squadmsg_shortcut( FORMATION_ITEM );
2605                         break;
2606
2607                 // wingman message: protect current target
2608                 case PROTECT_MESSAGE:
2609                         control_used(PROTECT_MESSAGE);
2610                         hud_squadmsg_shortcut( PROTECT_TARGET_ITEM );
2611                         break;
2612
2613                 // wingman message: cover me
2614                 case COVER_MESSAGE:
2615                         control_used(COVER_MESSAGE);
2616                         hud_squadmsg_shortcut( COVER_ME_ITEM );
2617                         break;
2618                 
2619                 // wingman message: warp out
2620                 case WARP_MESSAGE:
2621                         control_used(WARP_MESSAGE);
2622                         hud_squadmsg_shortcut( DEPART_ITEM );
2623                         break;
2624
2625                 case IGNORE_MESSAGE:
2626                         control_used(IGNORE_MESSAGE);
2627                         hud_squadmsg_shortcut( IGNORE_TARGET_ITEM );
2628                         break;
2629
2630                 // rearm message
2631                 case REARM_MESSAGE:
2632                         control_used(REARM_MESSAGE);
2633                         hud_squadmsg_rearm_shortcut();
2634                         break;
2635
2636                 // cycle to next radar range
2637                 case RADAR_RANGE_CYCLE:
2638                         control_used(RADAR_RANGE_CYCLE);
2639                         HUD_config.rp_dist++;
2640                         if ( HUD_config.rp_dist >= RR_MAX_RANGES )
2641                                 HUD_config.rp_dist = 0;
2642
2643                         HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Radar range set to %s", 38), Radar_range_text(HUD_config.rp_dist));
2644                         break;
2645
2646                 // toggle the squadmate messaging menu
2647                 case SQUADMSG_MENU:
2648                         control_used(SQUADMSG_MENU);
2649                         hud_squadmsg_toggle();                          // leave the details to the messaging code!!!
2650                         break;
2651
2652                 // show the mission goals screen
2653                 case SHOW_GOALS:
2654                         control_used(SHOW_GOALS);
2655                         gameseq_post_event( GS_EVENT_SHOW_GOALS );
2656                         break;
2657
2658                 // end the mission
2659                 case END_MISSION:
2660                         // in multiplayer, all end mission requests should go through the server
2661                         if(Game_mode & GM_MULTIPLAYER){                         
2662                                 multi_handle_end_mission_request();
2663                                 break;
2664                         }
2665
2666                         control_used(END_MISSION);
2667                         
2668                         if (collide_predict_large_ship(Player_obj, 200.0f)) {
2669                                 gamesnd_play_iface(SND_GENERAL_FAIL);
2670                                 HUD_printf(XSTR( "** WARNING ** Collision danger.  Warpout not activated.", 39));
2671                         } else if (ship_get_subsystem_strength( Player_ship, SUBSYSTEM_ENGINE ) < 0.1f) {
2672                                 gamesnd_play_iface(SND_GENERAL_FAIL);
2673                                 HUD_printf(XSTR( "Engine failure.  Cannot engage warp drive.", 40));
2674                         } else {
2675                                 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_START );
2676                         }                       
2677                         break;
2678
2679                 case ADD_REMOVE_ESCORT:
2680                         if ( Player_ai->target_objnum >= 0 ) {
2681                                 control_used(ADD_REMOVE_ESCORT);
2682                                 hud_add_remove_ship_escort(Player_ai->target_objnum);
2683                         }
2684                         break;
2685
2686                 case ESCORT_CLEAR:
2687                         control_used(ESCORT_CLEAR);
2688                         hud_escort_clear_all();
2689                         break;
2690
2691                 case TARGET_NEXT_ESCORT_SHIP:
2692                         control_used(TARGET_NEXT_ESCORT_SHIP);
2693                         hud_escort_target_next();
2694                         break;
2695
2696                 // increase weapon recharge rate
2697                 case INCREASE_WEAPON:
2698                         hud_gauge_popup_start(HUD_ETS_GAUGE);
2699                         return button_function_critical(INCREASE_WEAPON);
2700                         break;
2701
2702                 // decrease weapon recharge rate
2703                 case DECREASE_WEAPON:
2704                         hud_gauge_popup_start(HUD_ETS_GAUGE);
2705                         return button_function_critical(DECREASE_WEAPON);
2706                         break;
2707
2708                 // increase shield recharge rate
2709                 case INCREASE_SHIELD:
2710                         hud_gauge_popup_start(HUD_ETS_GAUGE);
2711                         return button_function_critical(INCREASE_SHIELD);
2712                         break;
2713
2714                 // decrease shield recharge rate
2715                 case DECREASE_SHIELD:
2716                         hud_gauge_popup_start(HUD_ETS_GAUGE);
2717                         return button_function_critical(DECREASE_SHIELD);
2718                         break;
2719
2720                 // increase energy to engines
2721                 case INCREASE_ENGINE:
2722                         hud_gauge_popup_start(HUD_ETS_GAUGE);
2723                         return button_function_critical(INCREASE_ENGINE);
2724                         break;
2725
2726                 // decrease energy to engines
2727                 case DECREASE_ENGINE:
2728                         hud_gauge_popup_start(HUD_ETS_GAUGE);
2729                         return button_function_critical(DECREASE_ENGINE);
2730                         break;
2731
2732                 case ETS_EQUALIZE:
2733                         hud_gauge_popup_start(HUD_ETS_GAUGE);
2734                         return button_function_critical(ETS_EQUALIZE);
2735                         break;
2736
2737                 // equalize shield energy to all quadrants
2738                 case SHIELD_EQUALIZE:
2739                         return button_function_critical(SHIELD_EQUALIZE);
2740                         break;
2741
2742                 // transfer shield energy to front
2743                 case SHIELD_XFER_TOP:
2744          return button_function_critical(SHIELD_XFER_TOP);
2745                         break;
2746
2747                 // transfer shield energy to rear
2748                 case SHIELD_XFER_BOTTOM:
2749                         return button_function_critical(SHIELD_XFER_BOTTOM);
2750                         break;
2751
2752                 // transfer shield energy to left
2753                 case SHIELD_XFER_LEFT:
2754                         return button_function_critical(SHIELD_XFER_LEFT);
2755                         break;
2756                 
2757                 // transfer shield energy to right
2758                 case SHIELD_XFER_RIGHT:
2759                         return button_function_critical(SHIELD_XFER_RIGHT);
2760                         break;
2761
2762                 // transfer energy to shield from weapons
2763                 case XFER_SHIELD:
2764                         return button_function_critical(XFER_SHIELD);
2765                         break;
2766
2767                 // transfer energy to weapons from shield
2768                 case XFER_LASER:
2769                         return button_function_critical(XFER_LASER);
2770                         break;
2771
2772                 // message all netplayers button
2773                 case MULTI_MESSAGE_ALL:
2774                         multi_msg_key_down(MULTI_MSG_ALL);
2775                         break;
2776
2777                 // message all friendlies button
2778                 case MULTI_MESSAGE_FRIENDLY:
2779                         multi_msg_key_down(MULTI_MSG_FRIENDLY);
2780                         break;
2781
2782                 // message all hostiles button
2783                 case MULTI_MESSAGE_HOSTILE:
2784                         multi_msg_key_down(MULTI_MSG_HOSTILE);
2785                         break;
2786
2787                 // message targeted ship (if player)
2788                 case MULTI_MESSAGE_TARGET:
2789                         multi_msg_key_down(MULTI_MSG_TARGET);
2790                         break;
2791
2792                 // if i'm an observer, zoom to my targeted object
2793                 case MULTI_OBSERVER_ZOOM_TO:
2794                         multi_obs_zoom_to_target();
2795                         break;          
2796 #ifndef MAKE_FS1
2797                 // toggle between high and low HUD contrast
2798                 case TOGGLE_HUD_CONTRAST:
2799                         gamesnd_play_iface(SND_USER_SELECT);
2800                         hud_toggle_contrast();
2801                         break;
2802
2803 #ifndef FS2_DEMO
2804                 // toggle network info
2805                 case MULTI_TOGGLE_NETINFO:
2806                         extern int Multi_display_netinfo;
2807                         Multi_display_netinfo = !Multi_display_netinfo;
2808                         break;
2809
2810                 // self destruct (multiplayer only)
2811                 case MULTI_SELF_DESTRUCT:
2812                         if(!(Game_mode & GM_MULTIPLAYER)){
2813                                 break;
2814                         }
2815
2816                         // bogus netplayer
2817                         if((Net_player == NULL) || (Net_player->player == NULL)){
2818                                 break;
2819                         }
2820
2821                         // blow myself up, if I'm the server
2822                         if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
2823                                 if((Net_player->player->objnum >= 0) && (Net_player->player->objnum < MAX_OBJECTS) && 
2824                                         (Objects[Net_player->player->objnum].type == OBJ_SHIP) && (Objects[Net_player->player->objnum].instance >= 0) && (Objects[Net_player->player->objnum].instance < MAX_SHIPS)){
2825
2826                                         ship_self_destruct(&Objects[Net_player->player->objnum]);
2827                                 }
2828                         }
2829                         // otherwise send a packet to the server
2830                         else {
2831                                 send_self_destruct_packet();
2832                         }
2833                         break;
2834 #endif
2835 #endif
2836                 // following are not handled here, but we need to bypass the Int3()
2837                 case LAUNCH_COUNTERMEASURE:
2838                 case VIEW_SLEW:
2839                 case ONE_THIRD_THROTTLE:
2840                 case TWO_THIRDS_THROTTLE:
2841                 case MINUS_5_PERCENT_THROTTLE:
2842                 case PLUS_5_PERCENT_THROTTLE:
2843                 case ZERO_THROTTLE:
2844                 case MAX_THROTTLE:
2845                         return 0;
2846
2847                 default:
2848                         Int3();
2849                         break;
2850         } // end switch
2851
2852         return 1;
2853 }
2854
2855 // Call functions for when buttons are pressed
2856 void button_info_do(button_info *bi)
2857 {
2858         int i, j;
2859
2860         for (i=0; i<NUM_BUTTON_FIELDS; i++) {
2861                 if ( bi->status[i] == 0 ){
2862                         continue;
2863                 }
2864
2865                 // at least one bit is set in the status integer
2866                 for (j=0; j<32; j++) {
2867
2868                         // check if the bit is set. If button_function returns 1 (implying the action was taken), then unset the bit
2869                         if ( bi->status[i] & (1 << j) ) {
2870                                 // always process buttons which are valid for demo playback
2871                                 if(button_function_demo_valid(32 * i + j)){
2872                                         bi->status[i] &= ~(1 << j);
2873                                 }
2874                                 // other buttons
2875                                 else {
2876                                         // if we're in demo playback, always clear the bits
2877                                         if(Game_mode & GM_DEMO_PLAYBACK){
2878                                                 bi->status[i] &= ~(1 << j);
2879                                         }
2880                                         // otherwise check as normal
2881                                         else if (button_function(32 * i + j)) {
2882                                                 bi->status[i] &= ~(1 << j);                                     
2883                                         }
2884                                 }
2885                         }
2886                 }
2887         }
2888 }
2889
2890
2891 // set the bit for the corresponding action n (BUTTON_ #define from KeyControl.h)
2892 void button_info_set(button_info *bi, int n)
2893 {
2894         int field_num, bit_num;
2895         
2896         field_num = n / 32;
2897         bit_num = n % 32;
2898
2899         bi->status[field_num] |= (1 << bit_num);        
2900 }
2901
2902 // unset the bit for the corresponding action n (BUTTON_ #define from KeyControl.h)
2903 void button_info_unset(button_info *bi, int n)
2904 {
2905         int field_num, bit_num;
2906         
2907         field_num = n / 32;
2908         bit_num = n % 32;
2909
2910         bi->status[field_num] &= ~(1 << bit_num);       
2911 }
2912
2913 int button_info_query(button_info *bi, int n)
2914 {
2915         return bi->status[n / 32] & (1 << (n % 32));
2916 }
2917
2918 // clear out the button_info struct
2919 void button_info_clear(button_info *bi)
2920 {
2921         int i;
2922
2923         for (i=0; i<NUM_BUTTON_FIELDS; i++) {
2924                 bi->status[i] = 0;
2925         }
2926 }
2927
2928 // strip out all noncritical keys from the button info struct
2929 void button_strip_noncritical_keys(button_info *bi)
2930 {
2931         int idx;
2932
2933         // clear out all noncritical keys
2934         for(idx=0;idx<Non_critical_key_set_size;idx++){
2935                 button_info_unset(bi,Non_critical_key_set[idx]);
2936         }
2937 }