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