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