]> icculus.org git repositories - taylor/freespace2.git/blob - src/gamesequence/gamesequence.cpp
2f2a096ca15620d3488a7727ee323f924adde645
[taylor/freespace2.git] / src / gamesequence / gamesequence.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/GameSequence/GameSequence.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * File to control Game Sequencing
16  *
17  * $Log$
18  * Revision 1.2  2002/06/09 04:41:17  relnev
19  * added copyright header
20  *
21  * Revision 1.1.1.1  2002/05/03 03:28:09  root
22  * Initial import.
23  *
24  * 
25  * 3     2/23/99 2:29p Dave
26  * First run of oldschool dogfight mode. 
27  * 
28  * 2     10/07/98 10:52a Dave
29  * Initial checkin.
30  * 
31  * 1     10/07/98 10:48a Dave
32  * 
33  * 65    5/15/98 12:09a Dave
34  * New tracker api code. New game tracker code. Finished up first run of
35  * the PXO screen. Fixed a few game server list exceptions.
36  * 
37  * 64    5/12/98 2:46a Dave
38  * Rudimentary communication between Parallax Online and freespace. Can
39  * get and store channel lists.
40  * 
41  * 63    5/06/98 1:12a Allender
42  * fix sequencing names, added nprintf to help respawn debugging
43  * 
44  * 62    4/25/98 7:39p Allender
45  * fixd some small hotkey stuff.  Worked on turret orientation being
46  * correct for multiplayer.  new sexpression called end-campaign will will
47  * end the main campaign
48  * 
49  * 61    4/23/98 7:08p John
50  * Removed some obsoleted states.
51  * 
52  * 60    4/16/98 4:31p Hoffoss
53  * Changed demo screen referenced to view cutscenes screen, which is now
54  * what it's called.
55  * 
56  * 59    4/02/98 5:40p Hoffoss
57  * Added the Load Mission screen to FreeSpace.
58  * 
59  * 58    3/11/98 5:32p Lawrance
60  * Fix up text arrays for events/states
61  * 
62  * 57    3/09/98 12:13a Lawrance
63  * Add support for Red Alert missions
64  * 
65  * 56    3/05/98 4:12p John
66  * Made Debug+F4 switch Glide and windowed.
67  * 
68  * 55    3/03/98 1:00p Hoffoss
69  * Added new command briefing event and state.
70  * 
71  * 54    3/02/98 4:23p Hoffoss
72  * Forgot to add state label.
73  * 
74  * 53    3/02/98 3:44p Hoffoss
75  * Added new Campaign Room state and event.
76  * 
77  * 52    2/21/98 11:58a John
78  * Put in some stuff to externalize strings
79  * 
80  * 51    2/19/98 6:26p Dave
81  * Fixed a few file xfer bugs. Tweaked mp team select screen. Put in
82  * initial support for player data uploading.
83  * 
84  * 50    2/18/98 10:21p Dave
85  * Ripped out old file xfer system. Put in brand new xfer system.
86  * 
87  * 49    2/08/98 5:07p Dave
88  * Put in support for multiplayer furball mode.
89  * 
90  * 48    1/28/98 6:21p Dave
91  * Made the standalone use ~8 megs less memory. Fixed multiplayer submenu
92  * endgame problem.
93  * 
94  * 47    1/23/98 5:43p Dave
95  * Finished bringing standalone up to speed. Coded in new host options
96  * screen.
97  * 
98  * 46    1/22/98 5:25p Dave
99  * Modified some pregame sequencing packets. Starting to repair broken
100  * standalone stuff.
101  * 
102  * 45    1/22/98 4:15p Hoffoss
103  * Added code to allow popup to tell player he needs to bind a key for the
104  * training mission.
105  * 
106  * 44    1/20/98 5:42p Dave
107  * Moved ingame join to its own module. Improved it a bit.
108  * 
109  * 43    1/19/98 12:57p Allender
110  * removed confusing comment
111  * 
112  * 42    1/19/98 12:56p Allender
113  * fix problem of freespace_start_misison possibly failing due to mission
114  * not properly loading (for single player only right now).
115  * 
116  * 41    1/15/98 6:12p Dave
117  * Fixed weapons loadout bugs with multiplayer respawning. Added
118  * multiplayer start screen. Fixed a few chatbox bugs.
119  * 
120  * 40    1/15/98 6:00p Hoffoss
121  * Added option to quit menu (in game) to restart the mission.  Doesn't
122  * seem to quite work, though.  Checking code in so someone else can look
123  * into it.
124  * 
125  * 39    1/05/98 10:05a Dave
126  * Big re-sequencing of server transfer. Centralized _all_ server transfer
127  * code to one module.
128  * 
129  * 38    12/30/97 4:28p Lawrance
130  * Give text descriptions for events, change debug output to give text
131  * desciption of event/state
132  * 
133  * 37    12/24/97 8:56p Lawrance
134  * took out obsolete state used for non-existant sound config screen
135  * 
136  * 36    11/19/97 8:28p Dave
137  * Hooked in Main Hall screen. Put in Anim support for ping ponging
138  * animations as well as general reversal of anim direction.
139  * 
140  * 35    11/15/97 2:36p Dave
141  * Added more multiplayer campaign support.
142  * 
143  * 34    11/13/97 7:01p Hoffoss
144  * Fixed GS_state_text[], which didn't match the current states we have
145  * available.
146  * 
147  * 33    11/10/97 6:02p Hoffoss
148  * Added new debug paused state.
149  * 
150  * 32    11/03/97 10:12p Hoffoss
151  * Finished up work on the hud message/mission log scrollback screen.
152  * 
153  * 31    10/22/97 11:00p Lawrance
154  * modify pop_and_discard() to allow discarding of all states on the stack
155  * 
156  * 30    10/22/97 5:08p John
157  * fixed a whole slew of bugs and clean up a bunch of stuff dealing with
158  * end of mission stuff.
159  * 
160  * 29    10/02/97 9:49p Hoffoss
161  * Added event evaluation analysis debug screen so we can determine the
162  * state of events and their sexp trees to track down logic problems and
163  * such.
164  * 
165  * 28    9/23/97 11:53p Lawrance
166  * add state do perform multiplayer on-line help
167  * 
168  * 27    9/22/97 4:55p Hoffoss
169  * Added a training message window display thingy.
170  * 
171  * 26    9/19/97 4:24p Allender
172  * added team selection state -- initialze player* variable in
173  * player_level_init
174  * 
175  * 25    9/18/97 10:17p Lawrance
176  * add help state for briefing
177  * 
178  * 24    9/18/97 10:15p Lawrance
179  * add help state for briefing
180  * 
181  * 23    7/14/97 12:03a Lawrance
182  * added navmap state
183  * 
184  * 22    6/13/97 2:30p Lawrance
185  * Added debriefings
186  * 
187  * 21    5/20/97 10:02a Lawrance
188  * added view medals screen
189  * 
190  * 20    4/28/97 2:17p Lawrance
191  * added help state for hotkey assignment screen
192  * 
193  * 19    4/25/97 3:41p Lawrance
194  * added support for hotkey assignment screen
195  * 
196  * 18    4/23/97 9:54a Lawrance
197  * made show goals screen a separate state
198  * 
199  * 17    4/22/97 11:06a Lawrance
200  * added credits state
201  * 
202  * 16    4/17/97 9:01p Allender
203  * start of campaign stuff.  Campaigns now stored in external file (no
204  * filenames in code).  Continuing campaign won't work at this point
205  * 
206  * 15    4/03/97 8:40p Lawrance
207  * add new player death states to GS_state_text[]
208  * 
209  * 14    3/05/97 5:04p Lawrance
210  * added new states for different context help
211  * 
212  * 13    1/09/97 12:41a Lawrance
213  * added function to pop a state without restoring that state
214  * 
215  * 12    12/22/96 3:41p Lawrance
216  * integrating energy transfer system
217  * 
218  * 11    12/09/96 2:35p Allender
219  * modifed game sequencing so that game_leave_state and game_enter_state
220  * are *always* called.
221  * 
222  * 10    12/08/96 1:54a Lawrance
223  * put check in to see if a state change request is invalid (ie already in
224  * that state)
225  * 
226  * 9     11/18/96 5:07p John
227  * Changed sequencing code to call entry,leave functions for each state
228  * change.   Added Shift+Pause debug pause thing.
229  * 
230  * 8     11/13/96 4:02p Lawrance
231  * complete over-haul of the menu system and the states associated with
232  * them
233  * 
234  * 7     10/23/96 9:08a Allender
235  * Removed primary and secondary goal complete states -- to be implemented
236  * later.
237  *
238 */
239
240 /*
241  *  All states for game sequencing are defined in GameSequence.h.
242  *  States should always be referred to using the macros.
243 */
244
245 #include "freespace.h"
246 #include "gamesequence.h"
247
248 // local defines
249 #define MAX_GAMESEQ_EVENTS              20              // maximum number of events on the game sequencing queue
250 #define GS_STACK_SIZE                   10              // maximum number of stacked states
251
252 // local variables
253 typedef struct state_stack {
254         int     current_state;
255         int     event_queue[MAX_GAMESEQ_EVENTS];
256         int     queue_tail, queue_head;
257 } state_stack;
258
259 // DO NOT MAKE THIS NON-STATIC!!!!
260 static state_stack gs[GS_STACK_SIZE];
261 static int gs_current_stack = -1;                                               // index of top state on stack.
262
263 static int state_reentry = 0;  // set if we are already in state processing
264 static int state_processing_event_post = 0;  // set if we are already processing an event to switch states
265 static int state_in_event_processer = 0;
266
267 // Text of state, corresponding to #define values for GS_STATE_*
268 //XSTR:OFF
269 const char *GS_event_text[] =
270 {
271         "GS_EVENT_MAIN_MENU",
272         "GS_EVENT_START_GAME",
273         "GS_EVENT_ENTER_GAME",
274         "GS_EVENT_START_GAME_QUICK",
275         "GS_EVENT_END_GAME",                                                                    
276         "GS_EVENT_QUIT_GAME",                                                           // 5
277         "GS_EVENT_PAUSE_GAME",
278         "GS_EVENT_PREVIOUS_STATE",
279         "GS_EVENT_OPTIONS_MENU",
280         "GS_EVENT_BARRACKS_MENU",                                                       
281         "GS_EVENT_TRAINING_MENU",                                                       // 10
282         "GS_EVENT_TECH_MENU",
283         "GS_EVENT_LOAD_MISSION_MENU",
284         "GS_EVENT_SHIP_SELECTION",
285         "GS_EVENT_TOGGLE_FULLSCREEN",                                           
286         "GS_EVENT_WEAPON_SELECT_HELP",                                  // 15
287         "GS_EVENT_START_BRIEFING",
288         "GS_EVENT_DEBUG_PAUSE_GAME",
289         "GS_EVENT_HUD_CONFIG",
290         "GS_EVENT_MULTI_SETUP",                                                         
291         "GS_EVENT_MULTI_JOIN_GAME",                                             // 20
292         "GS_EVENT_CONTROL_CONFIG",
293         "GS_EVENT_EVENT_DEBUG",
294         "GS_EVENT_MULTI_PROTO_CHOICE",
295         "GS_EVENT_SAVE_RESTORE",                                                        
296         "GS_EVENT_CHOOSE_SAVE_OR_RESTORE",                              // 25
297         "GS_EVENT_WEAPON_SELECTION",
298         "GS_EVENT_MISSION_LOG_SCROLLBACK",
299         "GS_EVENT_MAIN_MENU_HELP",                                                      
300         "GS_EVENT_GAMEPLAY_HELP",
301         "GS_EVENT_SHIP_SELECT_HELP",                                            // 30
302         "GS_EVENT_DEATH_DIED",
303         "GS_EVENT_DEATH_BLEW_UP",
304         "GS_EVENT_NEW_CAMPAIGN",
305         "GS_EVENT_CREDITS",
306         "GS_EVENT_SHOW_GOALS",                                                          // 35
307         "GS_EVENT_HOTKEY_SCREEN",
308         "GS_EVENT_HOTKEY_SCREEN_HELP",                                  
309         "GS_EVENT_VIEW_MEDALS",
310         "GS_EVENT_MULTI_HOST_SETUP",
311         "GS_EVENT_MULTI_CLIENT_SETUP",                                  // 40
312         "GS_EVENT_DEBRIEF",
313         "GS_EVENT_NAVMAP",                                                                      
314         "GS_EVENT_MULTI_JOIN_TRACKER",
315         "GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN",
316         "GS_EVENT_MULTI_STD_WAIT",                                                      // 45
317         "GS_EVENT_STANDALONE_MAIN",
318         "GS_EVENT_MULTI_PAUSE",
319         "GS_EVENT_BRIEFING_HELP",
320         "GS_EVENT_TEAM_SELECT",
321         "GS_EVENT_TRAINING_PAUSE",                                                      // 50   
322         "GS_EVENT_MULTI_HELP",                                                          
323         "GS_EVENT_INGAME_PRE_JOIN",
324         "GS_EVENT_PLAYER_WARPOUT_START",
325         "GS_EVENT_PLAYER_WARPOUT_START_FORCED",
326         "GS_EVENT_PLAYER_WARPOUT_STOP",                                 // 55
327         "GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1",                  
328         "GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2",
329         "GS_EVENT_PLAYER_WARPOUT_DONE",
330         "GS_EVENT_STANDALONE_POSTGAME",
331         "GS_EVENT_INITIAL_PLAYER_SELECT",                               // 60
332         "GS_EVENT_GAME_INIT",                                                           
333         "GS_EVENT_MULTI_MISSION_SYNC",
334         "GS_EVENT_MULTI_CAMPAIGN_SELECT",
335         "GS_EVENT_MULTI_SERVER_TRANSFER",
336         "GS_EVENT_MULTI_START_GAME",                                            // 65
337         "GS_EVENT_MULTI_HOST_OPTIONS",                                  
338         "GS_EVENT_MULTI_DOGFIGHT_DEBRIEF",
339         "GS_EVENT_CAMPAIGN_ROOM",
340         "GS_EVENT_CMD_BRIEF",
341         "GS_EVENT_TOGGLE_GLIDE",                                                        // 70
342         "GS_EVENT_RED_ALERT",                                                           
343         "GS_EVENT_SIMULATOR_ROOM",
344         "GS_EVENT_EMD_CAMPAIGN",
345         "GS_EVENT_PXO",
346         "GS_EVENT_PXO_HELP"
347 };
348 //XSTR:ON
349
350 // Text of state, corresponding to #define values for GS_STATE_*
351 //XSTR:OFF
352 const char *GS_state_text[] =
353 {
354         "NOT A VALID STATE",
355         "GS_STATE_MAIN_MENU",                                                           // 1
356         "GS_STATE_GAME_PLAY",
357         "GS_STATE_GAME_PAUSED",
358         "GS_STATE_QUIT_GAME",
359         "GS_STATE_OPTIONS_MENU",                                                        // 5
360         "GS_EVENT_WEAPON_SELECT_HELP",
361         "GS_STATE_BARRACKS_MENU",
362         "GS_STATE_TECH_MENU",
363         "GS_STATE_TRAINING_MENU",
364         "GS_STATE_LOAD_MISSION_MENU",                                           // 10
365         "GS_STATE_BRIEFING",
366         "GS_STATE_SHIP_SELECT",
367         "GS_STATE_DEBUG_PAUSED",
368         "GS_STATE_HUD_CONFIG",
369         "GS_STATE_MULTI_SETUP",                                                         // 15
370         "GS_STATE_MULTI_JOIN_GAME",
371         "GS_STATE_CONTROL_CONFIG",
372         "GS_STATE_MULTI_PROTO_CHOICE",
373         "GS_STATE_SAVE_RESTORE",
374         "GS_STATE_WEAPON_SELECT",                                                       // 20
375         "GS_STATE_MISSION_LOG_SCROLLBACK",
376         "GS_STATE_MAIN_MENU_HELP",
377         "GS_STATE_GAMEPLAY_HELP",
378         "GS_STATE_SHIP_SELECT_HELP",
379         "GS_STATE_DEATH_DIED",                                                          // 25
380         "GS_STATE_DEATH_BLEW_UP",
381         "GS_STATE_SIMULATOR_ROOM",
382         "GS_STATE_CREDITS",
383         "GS_STATE_SHOW_GOALS",
384         "GS_STATE_HOTKEY_SCREEN",                                                       // 30
385         "GS_STATE_HOTKEY_SCREEN_HELP",
386         "GS_STATE_VIEW_MEDALS",
387         "GS_STATE_MULTI_HOST_SETUP",
388         "GS_STATE_MULTI_CLIENT_SETUP",
389         "GS_STATE_DEBRIEF",                                                                     // 35
390         "GS_STATE_NAVMAP",
391         "GS_STATE_MULTI_JOIN_TRACKER",  
392         "GS_STATE_VIEW_CUTSCENES",
393         "GS_STATE_MULTI_STD_WAIT",
394         "GS_STATE_STANDALONE_MAIN",                                             // 40
395         "GS_STATE_MULTI_PAUSED",        
396         "GS_STATE_BRIEFING_HELP",
397         "GS_STATE_TEAM_SELECT",
398         "GS_STATE_TRAINING_PAUSED",
399         "GS_STATE_MULTI_HELP",                                                          // 45
400         "GS_STATE_INGAME_PRE_JOIN",                                             
401         "GS_STATE_EVENT_DEBUG",
402         "GS_STATE_STANDALONE_POSTGAME",
403         "GS_STATE_INITIAL_PLAYER_SELECT",
404         "GS_STATE_MULTI_MISSION_SYNC",                                  // 50
405         "GS_STATE_MULTI_SERVER_TRANSFER",                               
406         "GS_STATE_MULTI_START_GAME",
407         "GS_STATE_MULTI_HOST_OPTIONS",
408         "GS_STATE_MULTI_DOGFIGHT_DEBRIEF",                              
409         "GS_STATE_CAMPAIGN_ROOM",                                                       // 55
410         "GS_STATE_CMD_BRIEF",
411         "GS_STATE_RED_ALERT",
412         "GS_STATE_END_OF_CAMPAIGN",
413         "GS_STATE_PXO",
414         "GS_STATE_PXO_HELP"                                                             // 60
415 };
416 //XSTR:ON
417
418 void gameseq_init()
419 {
420         int i;
421
422         for (i=0; i<GS_STACK_SIZE; i++ )        {
423                 // gs[i].current_state = GS_STATE_MAIN_MENU;
424                 gs[i].current_state = 0;
425                 gs[i].queue_tail=0;
426                 gs[i].queue_head=0;
427         }
428
429         gs_current_stack = 0;
430         state_reentry = 0;
431         state_processing_event_post = 0;
432         state_in_event_processer = 0;
433 }
434
435 // gameseq_post_event posts a new game sequencing event onto the gameseq
436 // event queue
437
438 void gameseq_post_event( int event )
439 {
440         if (state_processing_event_post) {
441                 nprintf(("Warning", "Received post for event %s during state transtition. Find Allender if you are unsure if this is bad.\n", GS_event_text[event] ));
442         }
443
444         SDL_assert(gs[gs_current_stack].queue_tail < MAX_GAMESEQ_EVENTS);
445         gs[gs_current_stack].event_queue[gs[gs_current_stack].queue_tail++] = event;
446         if ( gs[gs_current_stack].queue_tail == MAX_GAMESEQ_EVENTS )
447                 gs[gs_current_stack].queue_tail = 0;
448 }
449
450 // returns one of the GS_EVENT_ id's on the game sequencing queue
451
452 int gameseq_get_event()
453 {
454         int event;
455
456         if ( gs[gs_current_stack].queue_head == gs[gs_current_stack].queue_tail )
457                 return -1;
458         event = gs[gs_current_stack].event_queue[gs[gs_current_stack].queue_head++];
459         if ( gs[gs_current_stack].queue_head == MAX_GAMESEQ_EVENTS )
460                 gs[gs_current_stack].queue_head = 0;
461
462         return event;
463 }          
464
465 // returns one of the GS_STATE_ macros
466 int gameseq_get_state(int depth)
467 {       
468         SDL_assert(depth <= gs_current_stack);
469                         
470         return gs[gs_current_stack - depth].current_state;
471 }
472
473 int gameseq_get_depth()
474 {
475         return gs_current_stack;
476 }
477
478 void gameseq_set_state(int new_state, int override)
479 {
480         int event, old_state;
481
482         if ( (new_state == gs[gs_current_stack].current_state) && !override )
483                 return;
484
485         old_state = gs[gs_current_stack].current_state;
486
487         // Flush all events!!
488         while ( (event = gameseq_get_event()) != -1 ) {
489                 mprintf(( "Throwing out event %d because of state set from %d to %d\n", event, old_state, new_state ));
490         }
491
492         SDL_assert( state_reentry == 1 );               // Get John! (Invalid state sequencing!)
493         SDL_assert( state_in_event_processer == 1 );            // can only call from game_process_event
494
495         state_processing_event_post++;
496         state_reentry++;
497         game_leave_state(gs[gs_current_stack].current_state,new_state);
498
499         gs[gs_current_stack].current_state = new_state;
500
501         game_enter_state(old_state,gs[gs_current_stack].current_state);
502         state_reentry--;
503         state_processing_event_post--;
504 }
505         
506 void gameseq_push_state( int new_state )
507 {
508         if ( new_state == gs[gs_current_stack].current_state )
509                 return;
510
511         int old_state = gs[gs_current_stack].current_state;
512
513         // Flush all events!!
514 // I commented out because I'm not sure if we should throw out events when pushing or not.
515 //      int event;
516 //      while( (event = gameseq_get_event()) != -1 )    {
517 //              mprintf(( "Throwing out event %d because of state push from %d to %d\n", event, old_state, new_state ));
518 //      }
519
520         SDL_assert( state_reentry == 1 );               // Get John! (Invalid state sequencing!)
521         SDL_assert( state_in_event_processer == 1 );            // can only call from game_process_event
522
523         gs_current_stack++;
524         SDL_assert(gs_current_stack < GS_STACK_SIZE);
525
526         state_processing_event_post++;
527         state_reentry++;
528         game_leave_state(old_state,new_state);
529
530         gs[gs_current_stack].current_state = new_state;
531         gs[gs_current_stack].queue_tail = 0;
532         gs[gs_current_stack].queue_head = 0;
533
534         game_enter_state(old_state,gs[gs_current_stack].current_state);
535         state_reentry--;
536         state_processing_event_post--;
537 }
538
539 void gameseq_pop_state()
540 {
541         int popped_state = 0;
542
543         SDL_assert(state_reentry == 1);         // Get John! (Invalid state sequencing!)
544
545         if (gs_current_stack >= 1) {
546                 int old_state;
547
548                 // set the old state to be the state which is about to be popped off the queue
549                 old_state = gs[gs_current_stack].current_state;
550
551                 // set the popped_state to be the state which is going to be moved into
552                 popped_state = gs[gs_current_stack-1].current_state;
553
554                 // leave the current state
555                 state_reentry++;
556                 game_leave_state(gs[gs_current_stack].current_state,popped_state);
557
558                 // set the popped_state to be the one we moved into
559                 gs_current_stack--;
560
561                 // swap all remaining events from the state which just got popped to this new state
562                 while(gs[gs_current_stack+1].queue_head != gs[gs_current_stack+1].queue_tail){
563                         gameseq_post_event(gs[gs_current_stack+1].event_queue[gs[gs_current_stack+1].queue_head++]);
564                 }
565
566                 game_enter_state(old_state, gs[gs_current_stack].current_state);
567                 state_reentry--;
568
569         }
570
571 }
572
573 // gameseq_pop_and_discard_state() is used to remove a state that was pushed onto the stack, but
574 // will never need to be popped.  An example of this is entering a state that may require returning
575 // to the previous state (then you would call gameseq_pop_state).  Or you may simply continue to
576 // another part of the game, to avoid filling up the stack with states that may never be popped, you
577 // call this function to discard the top of the gs.
578 //
579
580 void gameseq_pop_and_discard_state()
581 {
582         if (gs_current_stack > 0 ) {
583                 gs_current_stack--;
584         }
585 }
586
587 // Returns the last state pushed on stack
588 int gameseq_get_pushed_state()
589 {
590         if (gs_current_stack >= 1) {
591                 return gs[gs_current_stack-1].current_state;
592         } else  
593                 return -1;
594 }
595
596 // gameseq_process_events gets called every time through high level loops
597 // (i.e. game loops, main menu loop).  Function is responsible for pulling
598 // game sequence events off the queue and changing the state when necessary.
599 // Returns the current state.
600                 // pull events game sequence events off of the queue.  Process one at a time
601                 // based on the current state and the new event.
602
603 int gameseq_process_events()    
604 {
605         int event, old_state;
606         old_state = gs[gs_current_stack].current_state;
607
608         SDL_assert(state_reentry == 0);         // Get John! (Invalid state sequencing!)
609
610         while ( (event = gameseq_get_event()) != -1 ) {
611                 state_reentry++;
612                 state_in_event_processer++;
613                 game_process_event(gs[gs_current_stack].current_state, event);
614                 state_in_event_processer--;
615                 state_reentry--;
616                 // break when state changes so that code will get called at
617                 // least one frame for each state.
618                 if (old_state != gs[gs_current_stack].current_state)
619                         break;  
620         }
621
622         state_reentry++;
623         game_do_state(gs[gs_current_stack].current_state);
624         state_reentry--;
625
626         return gs[gs_current_stack].current_state;
627
628