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