]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/multi_campaign.cpp
Initial revision
[taylor/freespace2.git] / src / network / multi_campaign.cpp
1 /*
2  * $Logfile: /Freespace2/code/Network/multi_campaign.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * $Log$
8  * Revision 1.1  2002/05/03 03:28:10  root
9  * Initial revision
10  * 
11  * 
12  * 6     3/10/99 6:50p Dave
13  * Changed the way we buffer packets for all clients. Optimized turret
14  * fired packets. Did some weapon firing optimizations.
15  * 
16  * 5     3/09/99 6:24p Dave
17  * More work on object update revamping. Identified several sources of
18  * unnecessary bandwidth.
19  * 
20  * 4     12/12/98 3:17p Andsager
21  * Clean up mission eval, goal, event and mission scoring.
22  * 
23  * 3     11/19/98 8:03a Dave
24  * Full support for D3-style reliable sockets. Revamped packet lag/loss
25  * system, made it receiver side and at the lowest possible level.
26  * 
27  * 2     10/07/98 10:53a Dave
28  * Initial checkin.
29  * 
30  * 1     10/07/98 10:50a Dave
31  * 
32  * 31    6/13/98 6:01p Hoffoss
33  * Externalized all new (or forgot to be added) strings to all the code.
34  * 
35  * 30    5/23/98 7:09p Dave
36  * Fixed a potentially serious ingame join campaign bug.
37  * 
38  * 29    5/23/98 4:28p Jasen
39  * Insure goals pointer is not null.
40  * 
41  * 28    5/22/98 11:11a Allender
42  * more ingame join campaign fixes
43  * 
44  * 27    5/21/98 11:34p Allender
45  * ingame join fixes
46  * 
47  * 26    5/21/98 2:03a Allender
48  * fix for campaign misison names
49  * 
50  * 25    5/21/98 12:14a Allender
51  * fix ingame join problems
52  * 
53  * 24    5/20/98 3:25p Allender
54  * ingame join changes (which probably won't make the final version).
55  * Added RAS code into psnet
56  * 
57  * 23    5/19/98 8:35p Dave
58  * Revamp PXO channel listing system. Send campaign goals/events to
59  * clients for evaluation. Made lock button pressable on all screens. 
60  * 
61  * 22    5/08/98 5:05p Dave
62  * Go to the join game screen when quitting multiplayer. Fixed mission
63  * text chat bugs. Put mission type symbols on the create game list.
64  * Started updating standalone gui controls.
65  * 
66  * 21    5/06/98 12:36p Dave
67  * Make sure clients can leave the debrief screen easily at all times. Fix
68  * respawn count problem.
69  * 
70  * 20    5/05/98 7:25p Adam
71  * Fixed a few potential sequencing problems (packets getting lost or
72  * ignored when doing state transitions)
73  * 
74  * 19    5/05/98 5:02p Dave
75  * Fix end-of-campaign sequencing to work right. Make all individual
76  * missions of a campaign replayable.
77  * 
78  * 18    5/05/98 2:10p Dave
79  * Verify campaign support for testing. More new tracker code.
80  * 
81  * 17    5/04/98 10:39p Dave
82  * Put in endgame sequencing.  Need to check campaign situations.
83  * Realigned ship info on team select screen.
84  * 
85  * 16    4/22/98 5:52p Dave
86  * Large reworking of endgame sequencing. Updated host options screen for
87  * new artwork. Put in checks to end game if host leaves or if team
88  * captains leave mid-game. 
89  * 
90  * 15    4/20/98 4:56p Allender
91  * allow AI ships to respawn as many times as there are respawns in the
92  * mission.  
93  * 
94  * 14    4/06/98 10:24p Dave
95  * Fixed up Netgame.respawn for the standalone case.
96  * 
97  * 13    4/06/98 6:37p Dave
98  * Put in max_observers netgame server option. Make sure host is always
99  * defaulted to alpha 1 or zeta 1. Changed create game so that MAX_PLAYERS
100  * can always join but need to be kicked before commit can happen. Put in
101  * support for server ending a game and notifying clients of a special
102  * condition.
103  * 
104  * 12    3/24/98 4:59p Dave
105  * Fixed several ui bugs. Put in pre and post voice stream playback sound
106  * fx. Put in error specific popups for clients getting dropped from games
107  * through actions other than their own.
108  * 
109  * 11    3/17/98 12:16a Allender
110  * asteroids in multiplayer -- minor problems with position being correct
111  * 
112  * 10    3/16/98 2:35p Dave
113  * Numerous bug fixes. Made the "cue sound" sound play before incoming
114  * voice. 
115  * 
116  * 9     3/15/98 4:17p Dave
117  * Fixed oberver hud problems. Put in handy netplayer macros. Reduced size
118  * of network orientation matrices.
119  * 
120  * 8     3/12/98 10:45p Allender
121  * more ingame join stuff.  Mission events are not evaluated during
122  * critical ingame portion.  Wings/ships appear to work great.  Support
123  * ships still has a few problems I think 
124  * 
125  * 7     3/12/98 5:45p Dave
126  * Put in new observer HUD. Made it possible for observers to join at the
127  * beginning of a game and follow it around as an observer full-time.
128  * 
129  * 6     3/05/98 5:03p Dave
130  * More work on team vs. team support for multiplayer. Need to fix bugs in
131  * weapon select.
132  * 
133  * 5     3/03/98 5:12p Dave
134  * 50% done with team vs. team interface issues. Added statskeeping to
135  * secondary weapon blasts. Numerous multiplayer ui bug fixes.
136  * 
137  * 4     2/23/98 11:09p Dave
138  * Finished up multiplayer campaign support. Seems bug-free.
139  * 
140  * 3     2/23/98 5:08p Allender
141  * made net_signature an unsigned short.  Now using permanent and
142  * non-permanent object "pools".
143  * 
144  * 2     2/22/98 2:53p Dave
145  * Put in groundwork for advanced multiplayer campaign  options.
146  * 
147  * 1     2/20/98 4:39p Dave
148  * Split up mp campaign functionality into its own module.
149  *  
150  * $NoKeywords: $
151  */
152
153 #include <limits.h>
154
155 #include "gamesequence.h"
156 #include "multi.h"
157 #include "multiui.h"
158 #include "freespace.h"
159 #include "multimsgs.h"
160 #include "multiutil.h"
161 #include "popup.h"
162 #include "multi_xfer.h"
163 #include "multi_campaign.h"
164 #include "multi_endgame.h"
165 #include "stand_gui.h"
166 #include "missiongoals.h"
167
168 // ------------------------------------------------------------------------------------
169 // MULTIPLAYER CAMPAIGN DEFINES/VARS
170 //
171
172 // packet codes
173 #define MC_CODE_POOL                                                                    0                       // pool/weapons update
174 #define MC_CODE_DONE                                                                    1                       // campaign is "done"
175 #define MC_CODE_DEBRIEF                                                         2                       // debrief info
176 #define MC_CODE_START                                                           3                       // start campaign information
177
178 // packet code for ingame joining
179 #define MC_JIP_INITIAL_PACKET                                           1                       // initial data 
180 #define MC_JIP_GE_STATUS                                                        2                       // goal event status for all missions
181 #define MC_JIP_GOAL_NAMES                                                       3                       // goal names
182 #define MC_JIP_EVENT_NAMES                                                      4                       // event names
183 #define MC_JIP_END_DATA                                                         5                       // this is the end of the data
184
185
186 #define MC_INGAME_DATA_SLOP                                             50
187
188
189 // flags indicating the "accept" status of all players involved in a campaign
190 int Multi_campaign_accept_flags[MAX_PLAYERS];
191
192
193 // ------------------------------------------------------------------------------------
194 // MULTIPLAYER CAMPAIGN FUNCTIONS
195 //
196
197 // load a new campaign file or notify the standalone if we're not the server
198 void multi_campaign_start(char *filename)
199 {
200         int max_players;
201         char str[255];
202         
203         // set the netgame mode
204         Netgame.campaign_mode = MP_CAMPAIGN;            
205         
206         // set the campaign filename
207         strcpy(Netgame.campaign_name,filename);
208
209         // add the campaign mode flag
210         Game_mode |= GM_CAMPAIGN_MODE;
211
212         // if we're the server of the game we should also be loading the campaign up. otherwise, we let the standalone do it
213         if(Net_player->flags & NETINFO_FLAG_AM_MASTER){ 
214                 // start the campaign, passing 0 so we do _not_ load the savefile. this is only for starting
215                 // new campaigns
216                 mission_campaign_load(filename);
217                 mission_campaign_next_mission();
218                         
219                 // setup various filenames and mission names
220                 strcpy(Netgame.mission_name,Campaign.missions[Campaign.current_mission].name);
221                 strcpy(Netgame.campaign_name,filename);
222                 strcpy(Game_current_mission_filename,Netgame.mission_name);
223
224                 // if we're the standalone server, set the mission and campaign names
225                 if(Game_mode & GM_STANDALONE_SERVER){
226                         memset(str,0,255);
227                         strcpy(str,Netgame.mission_name);
228                         strcat(str," (");
229                         strcat(str,Netgame.campaign_name);
230                         strcat(str,")");
231
232                         // set the control on the stand_gui
233                         std_multi_set_standalone_mission_name(str);
234                 }
235
236                 // maybe override the Netgame.respawn setting
237                 max_players = mission_parse_get_multi_mission_info( Netgame.mission_name );                             
238                 Netgame.respawn = The_mission.num_respawns;
239                 nprintf(("Network","MULTI CAMPAIGN : overriding respawn setting with mission max %d\n",The_mission.num_respawns));              
240
241                 // send a "start campaign" packet
242                 multi_campaign_send_start();
243         }
244 }
245
246 // client-side start of a campaign
247 void multi_campaign_client_start()
248 {
249         memset(&Campaign,0,sizeof(Campaign));
250
251         // set campaign mode. what the hell.
252         Game_mode |= GM_CAMPAIGN_MODE;
253 }
254
255 // move everything and eveyrone into the next mission state
256 void multi_campaign_next_mission()
257 {
258         char str[255];
259
260         // flush the important data
261         multi_campaign_flush_data();
262
263         // call the campaign over function
264         mission_campaign_mission_over();                
265         
266         // now we should be sequencing through the next stage (mission load, etc)
267         // this will eventually be replaced with the real filename of the next mission
268         if(Campaign.current_mission != -1){
269                 strncpy(Game_current_mission_filename, Campaign.missions[Campaign.current_mission].name, MAX_FILENAME_LEN);
270                 strcpy(Netgame.mission_name,Game_current_mission_filename);                     
271
272                 // if we're the standalone server, set the mission and campaign names
273                 if(Game_mode & GM_STANDALONE_SERVER){
274                         memset(str,0,255);
275                         strcpy(str,Netgame.mission_name);
276                         strcat(str," (");
277                         strcat(str,Netgame.campaign_name);
278                         strcat(str,")");
279
280                         // set the control on the stand_gui
281                         std_multi_set_standalone_mission_name(str);
282                 }
283
284         }
285 }
286
287 // flush all important data between missions
288 void multi_campaign_flush_data()
289 {       
290         // blast the accept flags
291         memset(Multi_campaign_accept_flags,0,sizeof(int) * MAX_PLAYERS);
292
293         // flush mission stuff
294         multi_flush_mission_stuff();
295 }
296
297 // call in the debriefing stage to evaluate what we should be doing in regards to the campaign
298 // if player_status == 0, nothing should be done
299 //                  == 1, players want to continue to the next mission
300 //                  == 2, players want to repeat the previous mission
301 void multi_campaign_do_debrief(int player_status)
302 {
303         // the server (standalone or no)
304         if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Campaign.current_mission != -1) && player_status){                          
305                 // if players want to go to the next mission
306                 if(player_status == 1){
307                         // move the multiplayer campaign along
308                         multi_campaign_next_mission();                  
309
310                         // if we're at the end of the campaign
311                         if(Campaign.current_mission == -1){
312                                 // set the netgame state to be forming and continue
313                                 Netgame.game_state = NETGAME_STATE_FORMING;
314                                 send_netgame_update_packet();
315
316                                 if(Game_mode & GM_STANDALONE_SERVER){
317                                         gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
318                                 } else {
319                                         gameseq_post_event(GS_EVENT_MULTI_HOST_SETUP);
320                                 }
321                                 multi_reset_timestamps();
322                         }
323                         // if we're still in the campaign
324                         else {
325                                 Netgame.game_state = NETGAME_STATE_MISSION_SYNC;
326                                 send_netgame_update_packet();
327
328                                 Multi_sync_mode = MULTI_SYNC_PRE_BRIEFING;
329                                 gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC);
330
331                                 multi_reset_timestamps();
332                         }
333                 }
334                 // if the players want to replay the current mission
335                 else if(player_status == 2){
336                         Netgame.game_state = NETGAME_STATE_MISSION_SYNC;
337                         send_netgame_update_packet();
338
339                         Multi_sync_mode = MULTI_SYNC_PRE_BRIEFING;
340                         gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC);
341
342                         multi_reset_timestamps();
343                 } else {
344                         Int3();
345                 }                                                               
346         }                       
347 }
348
349 // display the done popup
350 void multi_campaign_done_popup()
351 {
352         popup(PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("The Campaign Is Complete. Thank You For Playing",643));
353         multi_quit_game(PROMPT_NONE);
354 }
355
356 // evaluate post mission goal stuff for the campaign and send all relevant stuff to clients
357 void multi_campaign_eval_debrief()
358 {
359         // evaluate mission stuff (fills in structures, etc).
360         // DKA 12/12/98 already done 
361         // mission_campaign_eval_next_mission();
362
363         // send the campaign debriefing packet
364         multi_campaign_send_debrief_info();
365 }
366
367 // clients should store mission goal/event names in the campaign now
368 void multi_campaign_client_store_goals(int mission_num)
369 {
370         int idx;
371         
372         // copy mission goals into the campaign goals
373         for(idx=0;idx<Num_goals;idx++){
374                 strcpy(Campaign.missions[mission_num].goals[idx].name,Mission_goals[idx].name);
375         }
376
377         // copy mission events into the campaign events
378         for(idx=0;idx<Num_mission_events;idx++){
379                 strcpy(Campaign.missions[mission_num].events[idx].name,Mission_events[idx].name);
380         }
381 }
382
383
384 // ------------------------------------------------------------------------------------
385 // MULTIPLAYER CAMPAIGN PACKET HANDLERS
386 //
387
388 // process a campaign update packet
389 void multi_campaign_process_update(ubyte *data, header *hinfo)
390 {
391         int offset = HEADER_LENGTH;
392         char fname[255];
393         ubyte val,spool_size,wpool_size;
394         ubyte code;
395         ubyte cur_mission,next_mission;
396         int idx;
397
398         // get the packet code
399         GET_DATA(code); 
400
401         switch(code){
402         case MC_CODE_DONE:
403                 // display the done popup
404                 multi_campaign_done_popup();
405                 break;
406
407         case MC_CODE_POOL:
408                 // get the campaign status byte
409                 GET_DATA(val);
410
411                 // if we're not in campaign mode, bash all weapons and ships to be "allowed"
412                 if(!val){
413                         // all ships
414                         for(idx=0;idx<MAX_SHIP_TYPES;idx++){
415                                 Campaign.ships_allowed[idx] = 1;
416                         }
417
418                         // all weapons
419                         for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
420                                 Campaign.weapons_allowed[idx] = 1;
421                         }
422                 } else {
423                         // clear the ships and weapons allowed arrays
424                         memset(Campaign.ships_allowed,0,MAX_SHIP_TYPES);
425                         memset(Campaign.weapons_allowed,0,MAX_WEAPON_TYPES);
426
427                         // get all ship classes
428                         GET_DATA(spool_size);
429                         for(idx=0;idx<spool_size;idx++){
430                                 GET_DATA(val);
431                                 Campaign.ships_allowed[val] = 1;
432                         } 
433         
434                         // get all weapon classes
435                         GET_DATA(wpool_size);
436                         for(idx=0;idx<wpool_size;idx++){
437                                 GET_DATA(val);
438                                 Campaign.weapons_allowed[val] = 1;
439                         }
440                 }       
441
442                 // ack the server
443                 Net_player->state = NETPLAYER_STATE_CPOOL_ACK;
444                 send_netplayer_update_packet();
445                 break;
446
447         case MC_CODE_DEBRIEF:
448                 GET_DATA(cur_mission);
449                 GET_DATA(next_mission);         
450
451                 // add the filename             
452                 GET_STRING(fname);
453                 Campaign.missions[cur_mission].name = strdup(fname);
454         
455                 // add the # of goals and events
456                 GET_DATA(val);
457                 Campaign.missions[cur_mission].num_goals = val;
458                 Campaign.missions[cur_mission].goals = (mgoal*)malloc(sizeof(mgoal) * val);
459
460                 GET_DATA(val);
461                 Campaign.missions[cur_mission].num_events = val;
462                 Campaign.missions[cur_mission].events = (mevent*)malloc(sizeof(mevent) * val);
463
464                 // add the goals
465                 for(idx=0;idx<Campaign.missions[cur_mission].num_goals;idx++){
466                         GET_DATA(val);
467                         Campaign.missions[cur_mission].goals[idx].status = val;
468                 }       
469
470                 // add the events
471                 for(idx=0;idx<Campaign.missions[cur_mission].num_events;idx++){
472                         GET_DATA(val);
473                         Campaign.missions[cur_mission].events[idx].status = val;
474                 }       
475
476                 // now set the "next mission to be the "current mission"
477                 Campaign.prev_mission = cur_mission;
478                 Campaign.current_mission = next_mission;
479
480                 // clients should store mission goal/event names in the campaign now
481                 multi_campaign_client_store_goals(cur_mission);
482                 break;
483
484         case MC_CODE_START:
485                 // clear the campaign
486                 multi_campaign_client_start();
487
488                 // read in the # of missions
489                 GET_DATA(Campaign.num_missions);
490
491                 // read in the mission filenames
492                 for(idx=0;idx<Campaign.num_missions;idx++){
493                         GET_STRING(fname);
494                         Campaign.missions[idx].name = strdup(fname);
495                 }
496                 break;
497         }
498
499         PACKET_SET_SIZE();
500 }
501
502 // send a "campaign finished" packet
503 void multi_campaign_send_done()
504 {
505         ubyte data[10],val;
506         int packet_size = 0;
507
508         // build the header
509         BUILD_HEADER(CAMPAIGN_UPDATE);
510
511         // add the code
512         val = MC_CODE_DONE;
513         ADD_DATA(val);
514
515         // broadcast the packet
516         multi_io_send_to_all_reliable(data, packet_size);
517 }
518
519 // send a campaign debrief update packet
520 void multi_campaign_send_debrief_info()
521 {
522         ubyte data[MAX_PACKET_SIZE],val;
523         int idx;
524         int packet_size = 0;
525
526         // build the header
527         BUILD_HEADER(CAMPAIGN_UPDATE);
528
529         // add the code
530         val = MC_CODE_DEBRIEF;
531         ADD_DATA(val);
532
533         // add the mission # we're including
534         val = (ubyte)Campaign.current_mission;
535         ADD_DATA(val);
536
537         // add the next mission
538         val = (ubyte)Campaign.next_mission;
539         ADD_DATA(val);
540
541         // add the filename
542         Assert(Campaign.missions[Campaign.current_mission].name != NULL);
543         ADD_STRING(Campaign.missions[Campaign.current_mission].name);
544         
545         // add the # of goals and events
546         val = (ubyte)Campaign.missions[Campaign.current_mission].num_goals;
547         ADD_DATA(val);
548         val = (ubyte)Campaign.missions[Campaign.current_mission].num_events;
549         ADD_DATA(val);
550
551         // add the goals
552         for(idx=0;idx<Campaign.missions[Campaign.current_mission].num_goals;idx++){
553                 val = (ubyte)Campaign.missions[Campaign.current_mission].goals[idx].status;
554                 ADD_DATA(val);
555         }       
556
557         // add the events
558         for(idx=0;idx<Campaign.missions[Campaign.current_mission].num_events;idx++){
559                 val = (ubyte)Campaign.missions[Campaign.current_mission].events[idx].status;
560                 ADD_DATA(val);
561         }       
562
563         // send to all players
564         multi_io_send_to_all_reliable(data, packet_size);
565 }
566
567 // send a campaign pool status packet
568 void multi_campaign_send_pool_status()
569 {
570         ubyte data[MAX_PACKET_SIZE],val;
571         int idx;
572         int spool_size;
573         int wpool_size;
574         int packet_size = 0;
575
576         // build the header
577         BUILD_HEADER(CAMPAIGN_UPDATE);
578
579         // add the code
580         val = MC_CODE_POOL;
581         ADD_DATA(val);
582
583         // if we're not in campaign mode, send a single byte saying "allow all ships and weapons"
584         if(!(Game_mode & GM_CAMPAIGN_MODE)){
585                 val = 0x0;
586                 ADD_DATA(val);
587         }
588         // otherwise add all relevant ship/weapon pool data
589         else {
590                 val = 0x1;
591                 ADD_DATA(val);
592
593                 // determine how many ship types we're going to add
594                 spool_size = 0;
595                 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
596                         if(Campaign.ships_allowed[idx]){
597                                 spool_size++;
598                         }
599                 }
600                 
601                 // determine how many weapon types we're going to add
602                 wpool_size = 0;
603                 for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
604                         if(Campaign.weapons_allowed[idx]){
605                                 wpool_size++;
606                         }
607                 }
608
609                 // make sure it'll all fit into this packet
610                 Assert((wpool_size + spool_size) < 480);
611
612                 // add all ship types
613                 val = (ubyte)spool_size;
614                 ADD_DATA(val);
615                 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
616                         if(Campaign.ships_allowed[idx]){
617                                 val = (ubyte)idx;
618                                 ADD_DATA(val);
619                         }
620                 }               
621
622                 // add all weapon types
623                 val = (ubyte)wpool_size;
624                 ADD_DATA(val);
625                 for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
626                         if(Campaign.weapons_allowed[idx]){
627                                 val = (ubyte)idx;
628                                 ADD_DATA(val);
629                         }
630                 }
631         }
632
633         // send to all players
634         Assert(Net_player->flags & NETINFO_FLAG_AM_MASTER);     
635         multi_io_send_to_all_reliable(data, packet_size);
636
637         // notification message
638         multi_common_add_text(XSTR("Campaign ship/weapon pool\n",644),1);
639 }
640
641 // send a "start campaign" packet
642 void multi_campaign_send_start(net_player *pl)
643 {
644         ubyte data[MAX_PACKET_SIZE],val;
645         int idx;
646         int packet_size = 0;
647
648         // build the header
649         BUILD_HEADER(CAMPAIGN_UPDATE);
650
651         // add the code
652         val = MC_CODE_START;
653         ADD_DATA(val);
654
655         // add the # of missions, and their filenames
656         ADD_DATA(Campaign.num_missions);
657         for(idx=0;idx<Campaign.num_missions;idx++){
658                 Assert(Campaign.missions[idx].name != NULL);
659                 ADD_STRING(Campaign.missions[idx].name);
660         }
661
662         // if we're targeting a specific player
663         if(pl != NULL){
664                 multi_io_send_reliable(pl, data, packet_size);
665         }
666         // send to all players
667         else {  
668                 multi_io_send_to_all_reliable(data, packet_size);
669         }
670 }
671
672 // campaign start packet for ingame joiners.  Sends filename and goal/event name and status
673 void multi_campaign_send_ingame_start( net_player *pl )
674 {
675         ubyte data[MAX_PACKET_SIZE], packet_type, num_goals, num_events, *ptr;
676         int packet_size, i, j;
677
678         Assert( pl != NULL );
679         packet_size = 0;
680
681         if ( Game_mode & GM_CAMPAIGN_MODE ) {
682
683                 // first -- add the number of missions and the mission names
684                 // add the # of missions, and their filenames
685                 BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
686                 packet_type = MC_JIP_INITIAL_PACKET;
687                 ADD_DATA(packet_type);
688                 ADD_DATA(Campaign.num_missions);
689                 for( i = 0; i < Campaign.num_missions; i++) {
690                         Assert(Campaign.missions[i].name != NULL);
691                         ADD_STRING(Campaign.missions[i].name);
692                 }               
693                 multi_io_send_reliable(pl, data, packet_size);
694
695                 // send the number and status of all goals event for all previous missions
696                 for (i = 0; i < Campaign.num_missions; i++ ) {
697                         ubyte status;
698
699                         // don't send data for the current mission being played, or if both goals and events are 0
700                         Assert( Campaign.missions[i].num_goals < UCHAR_MAX );
701                         Assert( Campaign.missions[i].num_events < UCHAR_MAX );
702                         num_goals = (ubyte)Campaign.missions[i].num_goals;
703                         num_events = (ubyte)Campaign.missions[i].num_events;
704
705                         // don't do anything if mission hasn't been completed
706                         if ( !Campaign.missions[i].completed )
707                                 continue;
708
709                         // add the mission number and the goal/event status
710                         BUILD_HEADER( CAMPAIGN_UPDATE_INGAME );
711                         packet_type = MC_JIP_GE_STATUS;
712                         ADD_DATA( packet_type );
713                         ADD_DATA(i);
714                         ADD_DATA( num_goals );
715                         for ( j = 0; j < num_goals; j++ ) {
716                                 status = (ubyte)Campaign.missions[i].goals[j].status;
717                                 ADD_DATA(status);
718                         }
719
720                         // now the events
721                         ADD_DATA( num_events );
722                         for ( j = 0; j < num_events; j++ ) {
723                                 status = (ubyte)Campaign.missions[i].events[j].status;
724                                 ADD_DATA(status);
725                         }
726                         
727                         multi_io_send_reliable(pl, data, packet_size);
728                 }       
729
730                 // send the goal/event names.
731                 for ( i = 0; i < Campaign.num_missions; i++ ) {
732                         ubyte goal_count, starting_goal_num;
733
734                         // first the goal names
735                         Assert( Campaign.missions[i].num_goals < UCHAR_MAX );
736                         num_goals = (ubyte)Campaign.missions[i].num_goals;
737
738                         // don't do anything if mission hasn't been completed
739                         if ( !Campaign.missions[i].completed ){
740                                 continue;
741                         }
742
743                         BUILD_HEADER( CAMPAIGN_UPDATE_INGAME );
744                         packet_type = MC_JIP_GOAL_NAMES;
745                         ADD_DATA(packet_type);
746                         ADD_DATA(i);
747
748                         // save a pointer so we can put the number of goals written here.
749                         ptr = &data[packet_size];
750
751                         goal_count = 0;
752                         ADD_DATA( goal_count );
753
754                         starting_goal_num = 0;
755                         ADD_DATA( starting_goal_num );
756
757                         for ( j = 0; j < num_goals; j++ ) {
758                                 ADD_STRING( Campaign.missions[i].goals[j].name );
759                                 goal_count++;
760
761                                 // if packet will get too big, send it off.
762                                 if ( (packet_size + MC_INGAME_DATA_SLOP) > MAX_PACKET_SIZE ) {
763                                         *ptr = goal_count;                                      
764                                         multi_io_send_reliable(pl, data, packet_size);
765                                         BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
766                                         packet_type = MC_JIP_GOAL_NAMES;
767                                         ADD_DATA( packet_type );
768                                         ADD_DATA(i);
769                                         ptr = &data[packet_size];
770                                         goal_count = 0;
771                                         ADD_DATA( goal_count );
772                                         starting_goal_num = (ubyte)j;
773                                         ADD_DATA( starting_goal_num );
774                                 }
775                         }
776
777                         *ptr = goal_count;                      
778                         multi_io_send_reliable(pl, data, packet_size);
779                 }
780
781                 // send the goal/event names.
782                 for ( i = 0; i < Campaign.num_missions; i++ ) {
783                         ubyte event_count, starting_event_num;
784
785                         // first the goal names
786                         Assert( Campaign.missions[i].num_events < UCHAR_MAX );
787                         num_events = (ubyte)Campaign.missions[i].num_events;
788
789                         // don't do anything if mission hasn't been completed
790                         if ( !Campaign.missions[i].completed )
791                                 continue;
792
793                         BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
794                         packet_type = MC_JIP_EVENT_NAMES;
795                         ADD_DATA(packet_type);
796                         ADD_DATA(i);
797
798                         // save a pointer so we can put the number of goals written here.
799                         ptr = &data[packet_size];
800
801                         event_count = 0;
802                         ADD_DATA( event_count );
803
804                         starting_event_num = 0;
805                         ADD_DATA( starting_event_num );
806
807                         for ( j = 0; j < num_events; j++ ) {
808                                 ADD_STRING( Campaign.missions[i].events[j].name );
809                                 event_count++;
810
811                                 // if packet will get too big, send it off.
812                                 if ( (packet_size + MC_INGAME_DATA_SLOP) > MAX_PACKET_SIZE ) {
813                                         *ptr = event_count;                                     
814                                         multi_io_send_reliable(pl, data, packet_size);
815                                         BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
816                                         packet_type = MC_JIP_EVENT_NAMES;
817                                         ADD_DATA( packet_type );
818                                         ADD_DATA(i);
819                                         ptr = &data[packet_size];
820                                         event_count = 0;
821                                         ADD_DATA( event_count );
822                                         starting_event_num = (ubyte)j;
823                                         ADD_DATA( starting_event_num );
824                                 }
825                         }
826
827                         *ptr = event_count;                     
828                         multi_io_send_reliable(pl, data, packet_size);
829                 }
830         }
831
832         // add the stop byte
833         BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
834         packet_type = MC_JIP_END_DATA;
835         ADD_DATA(packet_type);  
836         multi_io_send_reliable(pl, data, packet_size);
837 }
838
839 void multi_campaign_process_ingame_start( ubyte *data, header *hinfo )
840 {
841         int offset, mission_num, i;
842         ubyte packet_type, num_goals, num_events, status, starting_num;
843         char fname[255];
844
845         offset = HEADER_LENGTH;
846
847         GET_DATA( packet_type );
848         switch( packet_type ) {
849         case MC_JIP_INITIAL_PACKET:
850
851                 // clear out the names of the missions
852                 mission_campaign_close();                                               // should free all data structures which need to be freed
853
854                 // get the number of campaigns and their names.
855                 GET_DATA(Campaign.num_missions);
856                 for( i = 0; i < Campaign.num_missions ; i++) {
857                         GET_STRING(fname);
858                         Campaign.missions[i].name = strdup(fname);
859                 }
860
861                 break;
862
863         case MC_JIP_GE_STATUS:
864                 
865                 GET_DATA( mission_num );
866                 GET_DATA( num_goals );
867                 // need to malloc out the data
868                 Assert( Campaign.missions[mission_num].num_goals == 0 );
869                 Campaign.missions[mission_num].num_goals = num_goals;
870                 if ( num_goals > 0 ){
871                         Campaign.missions[mission_num].goals = (mgoal *)malloc( sizeof(mgoal) * num_goals );
872                 }
873                 for ( i = 0; i < num_goals; i++ ) {
874                         GET_DATA(status);
875                         // AL: .goals was a NULL pointer here!  I have no idea why.  Putting
876                         // in a check to avoid the unhandled exception
877                         if ( Campaign.missions[mission_num].goals ) {
878                                 Campaign.missions[mission_num].goals[i].status = status;
879                         }
880                 }
881
882                 // now the events
883                 GET_DATA( num_events );
884                 // need to malloc out the data
885                 Assert( Campaign.missions[mission_num].num_events == 0 );
886                 Campaign.missions[mission_num].num_events = num_events;
887                 if ( num_events > 0 ){
888                         Campaign.missions[mission_num].events = (mevent *)malloc( sizeof(mevent) * num_events );
889                 }
890
891                 for ( i = 0; i < num_events; i++ ) {
892                         GET_DATA(status);
893                         Campaign.missions[mission_num].events[i].status = status;
894                 }
895                 break;
896
897         case MC_JIP_GOAL_NAMES:
898                 GET_DATA( mission_num );
899                 GET_DATA( num_goals );
900                 GET_DATA( starting_num );
901                 for ( i = starting_num; i < (starting_num + num_goals); i++ ) {
902                         GET_STRING(Campaign.missions[mission_num].goals[i].name);
903                 }
904                 break;
905
906         case MC_JIP_EVENT_NAMES:
907                 GET_DATA( mission_num );
908                 GET_DATA( num_events );
909                 GET_DATA( starting_num );
910                 for ( i = starting_num; i < (starting_num + num_events); i++ ) {
911                         GET_STRING(Campaign.missions[mission_num].events[i].name);
912                 }
913                 break;
914
915         case MC_JIP_END_DATA:
916                 Net_player->state = NETPLAYER_STATE_INGAME_CINFO;
917                 send_netplayer_update_packet();
918                 break;
919         }
920
921         PACKET_SET_SIZE();
922 }