]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/multi_campaign.cpp
fix display of goals (proper reset, expand)
[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_server.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         SDL_strlcpy(Netgame.campaign_name, filename, SDL_arraysize(Netgame.campaign_name));
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                 SDL_strlcpy(Netgame.mission_name ,Campaign.missions[Campaign.current_mission].name, SDL_arraysize(Netgame.mission_name));
241                 SDL_strlcpy(Netgame.campaign_name, filename, SDL_arraysize(Netgame.campaign_name));
242                 SDL_strlcpy(Game_current_mission_filename, Netgame.mission_name, SDL_arraysize(Game_current_mission_filename));
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                         SDL_snprintf(str, SDL_arraysize(str), "%s (%s)", Netgame.mission_name,Netgame.campaign_name );
248
249                         // set the control on the stand_gui
250                         std_multi_set_standalone_mission_name(str);
251                 }
252
253                 // maybe override the Netgame.respawn setting
254         //      max_players = mission_parse_get_multi_mission_info( Netgame.mission_name );
255                 Netgame.respawn = The_mission.num_respawns;
256                 nprintf(("Network","MULTI CAMPAIGN : overriding respawn setting with mission max %d\n",The_mission.num_respawns));              
257
258                 // send a "start campaign" packet
259                 multi_campaign_send_start();
260         }
261 }
262
263 // client-side start of a campaign
264 void multi_campaign_client_start()
265 {
266         memset(&Campaign,0,sizeof(Campaign));
267
268         // set campaign mode. what the hell.
269         Game_mode |= GM_CAMPAIGN_MODE;
270 }
271
272 // move everything and eveyrone into the next mission state
273 void multi_campaign_next_mission()
274 {
275         char str[255];
276
277         // flush the important data
278         multi_campaign_flush_data();
279
280         // call the campaign over function
281         mission_campaign_mission_over();                
282         
283         // now we should be sequencing through the next stage (mission load, etc)
284         // this will eventually be replaced with the real filename of the next mission
285         if(Campaign.current_mission != -1){
286                 SDL_strlcpy(Game_current_mission_filename, Campaign.missions[Campaign.current_mission].name, SDL_arraysize(Game_current_mission_filename));
287                 SDL_strlcpy(Netgame.mission_name, Game_current_mission_filename, SDL_arraysize(Netgame.mission_name));
288
289                 // if we're the standalone server, set the mission and campaign names
290                 if(Game_mode & GM_STANDALONE_SERVER){
291                         memset(str,0,255);
292                         SDL_snprintf(str, SDL_arraysize(str), "%s (%s)", Netgame.mission_name, Netgame.campaign_name);
293
294                         // set the control on the stand_gui
295                         std_multi_set_standalone_mission_name(str);
296                 }
297
298         }
299 }
300
301 // flush all important data between missions
302 void multi_campaign_flush_data()
303 {       
304         // blast the accept flags
305         memset(Multi_campaign_accept_flags,0,sizeof(int) * MAX_PLAYERS);
306
307         // flush mission stuff
308         multi_flush_mission_stuff();
309 }
310
311 // call in the debriefing stage to evaluate what we should be doing in regards to the campaign
312 // if player_status == 0, nothing should be done
313 //                  == 1, players want to continue to the next mission
314 //                  == 2, players want to repeat the previous mission
315 void multi_campaign_do_debrief(int player_status)
316 {
317         // the server (standalone or no)
318         if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Campaign.current_mission != -1) && player_status){                          
319                 // if players want to go to the next mission
320                 if(player_status == 1){
321                         // move the multiplayer campaign along
322                         multi_campaign_next_mission();                  
323
324                         // if we're at the end of the campaign
325                         if(Campaign.current_mission == -1){
326                                 // set the netgame state to be forming and continue
327                                 Netgame.game_state = NETGAME_STATE_FORMING;
328                                 send_netgame_update_packet();
329
330                                 if(Game_mode & GM_STANDALONE_SERVER){
331                                         gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
332                                 } else {
333                                         gameseq_post_event(GS_EVENT_MULTI_HOST_SETUP);
334                                 }
335                                 multi_reset_timestamps();
336                         }
337                         // if we're still in the campaign
338                         else {
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                         }
347                 }
348                 // if the players want to replay the current mission
349                 else if(player_status == 2){
350                         Netgame.game_state = NETGAME_STATE_MISSION_SYNC;
351                         send_netgame_update_packet();
352
353                         Multi_sync_mode = MULTI_SYNC_PRE_BRIEFING;
354                         gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC);
355
356                         multi_reset_timestamps();
357                 } else {
358                         Int3();
359                 }                                                               
360         }                       
361 }
362
363 // display the done popup
364 void multi_campaign_done_popup()
365 {
366         popup(PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("The Campaign Is Complete. Thank You For Playing",643));
367         multi_quit_game(PROMPT_NONE);
368 }
369
370 // evaluate post mission goal stuff for the campaign and send all relevant stuff to clients
371 void multi_campaign_eval_debrief()
372 {
373         // evaluate mission stuff (fills in structures, etc).
374         // DKA 12/12/98 already done 
375         // mission_campaign_eval_next_mission();
376
377         // send the campaign debriefing packet
378         multi_campaign_send_debrief_info();
379 }
380
381 // clients should store mission goal/event names in the campaign now
382 void multi_campaign_client_store_goals(int mission_num)
383 {
384         int idx;
385         
386         // copy mission goals into the campaign goals
387         for(idx=0;idx<Num_goals;idx++){
388                 SDL_strlcpy(Campaign.missions[mission_num].goals[idx].name, Mission_goals[idx].name, NAME_LENGTH);
389         }
390
391         // copy mission events into the campaign events
392         for(idx=0;idx<Num_mission_events;idx++){
393                 SDL_strlcpy(Campaign.missions[mission_num].events[idx].name, Mission_events[idx].name, NAME_LENGTH);
394         }
395 }
396
397
398 // ------------------------------------------------------------------------------------
399 // MULTIPLAYER CAMPAIGN PACKET HANDLERS
400 //
401
402 // process a campaign update packet
403 void multi_campaign_process_update(ubyte *data, header *hinfo)
404 {
405         int offset = HEADER_LENGTH;
406         char fname[255];
407         ubyte val,spool_size,wpool_size;
408         ubyte code;
409         ubyte cur_mission,next_mission;
410         int idx;
411
412         // get the packet code
413         GET_DATA(code); 
414
415         switch(code){
416         case MC_CODE_DONE:
417                 // display the done popup
418                 multi_campaign_done_popup();
419                 break;
420
421         case MC_CODE_POOL:
422                 // get the campaign status byte
423                 GET_DATA(val);
424
425                 // if we're not in campaign mode, bash all weapons and ships to be "allowed"
426                 if(!val){
427                         // all ships
428                         for(idx=0;idx<MAX_SHIP_TYPES;idx++){
429                                 Campaign.ships_allowed[idx] = 1;
430                         }
431
432                         // all weapons
433                         for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
434                                 Campaign.weapons_allowed[idx] = 1;
435                         }
436                 } else {
437                         // clear the ships and weapons allowed arrays
438                         memset(Campaign.ships_allowed,0,MAX_SHIP_TYPES);
439                         memset(Campaign.weapons_allowed,0,MAX_WEAPON_TYPES);
440
441                         // get all ship classes
442                         GET_DATA(spool_size);
443                         for(idx=0;idx<spool_size;idx++){
444                                 GET_DATA(val);
445                                 Campaign.ships_allowed[val] = 1;
446                         } 
447         
448                         // get all weapon classes
449                         GET_DATA(wpool_size);
450                         for(idx=0;idx<wpool_size;idx++){
451                                 GET_DATA(val);
452                                 Campaign.weapons_allowed[val] = 1;
453                         }
454                 }       
455
456                 // ack the server
457                 Net_player->state = NETPLAYER_STATE_CPOOL_ACK;
458                 send_netplayer_update_packet();
459                 break;
460
461         case MC_CODE_DEBRIEF:
462                 GET_DATA(cur_mission);
463                 GET_DATA(next_mission);         
464
465                 // add the filename             
466                 GET_STRING(fname);
467                 Campaign.missions[cur_mission].name = strdup(fname);
468         
469                 // add the # of goals and events
470                 GET_DATA(val);
471                 Campaign.missions[cur_mission].num_goals = val;
472                 Campaign.missions[cur_mission].goals = (mgoal*)malloc(sizeof(mgoal) * val);
473
474                 GET_DATA(val);
475                 Campaign.missions[cur_mission].num_events = val;
476                 Campaign.missions[cur_mission].events = (mevent*)malloc(sizeof(mevent) * val);
477
478                 // add the goals
479                 for(idx=0;idx<Campaign.missions[cur_mission].num_goals;idx++){
480                         GET_DATA(val);
481                         Campaign.missions[cur_mission].goals[idx].status = val;
482                 }       
483
484                 // add the events
485                 for(idx=0;idx<Campaign.missions[cur_mission].num_events;idx++){
486                         GET_DATA(val);
487                         Campaign.missions[cur_mission].events[idx].status = val;
488                 }       
489
490                 // now set the "next mission to be the "current mission"
491                 Campaign.prev_mission = cur_mission;
492                 Campaign.current_mission = next_mission;
493
494                 // clients should store mission goal/event names in the campaign now
495                 multi_campaign_client_store_goals(cur_mission);
496                 break;
497
498         case MC_CODE_START:
499                 // clear the campaign
500                 multi_campaign_client_start();
501
502                 // read in the # of missions
503                 GET_INT(Campaign.num_missions);
504
505                 // read in the mission filenames
506                 for(idx=0;idx<Campaign.num_missions;idx++){
507                         GET_STRING(fname);
508                         Campaign.missions[idx].name = strdup(fname);
509                 }
510                 break;
511         }
512
513         PACKET_SET_SIZE();
514 }
515
516 // send a "campaign finished" packet
517 void multi_campaign_send_done()
518 {
519         ubyte data[10],val;
520         int packet_size = 0;
521
522         // build the header
523         BUILD_HEADER(CAMPAIGN_UPDATE);
524
525         // add the code
526         val = MC_CODE_DONE;
527         ADD_DATA(val);
528
529         // broadcast the packet
530         multi_io_send_to_all_reliable(data, packet_size);
531 }
532
533 // send a campaign debrief update packet
534 void multi_campaign_send_debrief_info()
535 {
536         ubyte data[MAX_PACKET_SIZE],val;
537         int idx;
538         int packet_size = 0;
539
540         // build the header
541         BUILD_HEADER(CAMPAIGN_UPDATE);
542
543         // add the code
544         val = MC_CODE_DEBRIEF;
545         ADD_DATA(val);
546
547         // add the mission # we're including
548         val = (ubyte)Campaign.current_mission;
549         ADD_DATA(val);
550
551         // add the next mission
552         val = (ubyte)Campaign.next_mission;
553         ADD_DATA(val);
554
555         // add the filename
556         SDL_assert(Campaign.missions[Campaign.current_mission].name != NULL);
557         ADD_STRING(Campaign.missions[Campaign.current_mission].name);
558         
559         // add the # of goals and events
560         val = (ubyte)Campaign.missions[Campaign.current_mission].num_goals;
561         ADD_DATA(val);
562         val = (ubyte)Campaign.missions[Campaign.current_mission].num_events;
563         ADD_DATA(val);
564
565         // add the goals
566         for(idx=0;idx<Campaign.missions[Campaign.current_mission].num_goals;idx++){
567                 val = (ubyte)Campaign.missions[Campaign.current_mission].goals[idx].status;
568                 ADD_DATA(val);
569         }       
570
571         // add the events
572         for(idx=0;idx<Campaign.missions[Campaign.current_mission].num_events;idx++){
573                 val = (ubyte)Campaign.missions[Campaign.current_mission].events[idx].status;
574                 ADD_DATA(val);
575         }       
576
577         // send to all players
578         multi_io_send_to_all_reliable(data, packet_size);
579 }
580
581 // send a campaign pool status packet
582 void multi_campaign_send_pool_status()
583 {
584         ubyte data[MAX_PACKET_SIZE],val;
585         int idx;
586         int spool_size;
587         int wpool_size;
588         int packet_size = 0;
589
590         // build the header
591         BUILD_HEADER(CAMPAIGN_UPDATE);
592
593         // add the code
594         val = MC_CODE_POOL;
595         ADD_DATA(val);
596
597         // if we're not in campaign mode, send a single byte saying "allow all ships and weapons"
598         if(!(Game_mode & GM_CAMPAIGN_MODE)){
599                 val = 0x0;
600                 ADD_DATA(val);
601         }
602         // otherwise add all relevant ship/weapon pool data
603         else {
604                 val = 0x1;
605                 ADD_DATA(val);
606
607                 // determine how many ship types we're going to add
608                 spool_size = 0;
609                 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
610                         if(Campaign.ships_allowed[idx]){
611                                 spool_size++;
612                         }
613                 }
614                 
615                 // determine how many weapon types we're going to add
616                 wpool_size = 0;
617                 for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
618                         if(Campaign.weapons_allowed[idx]){
619                                 wpool_size++;
620                         }
621                 }
622
623                 // make sure it'll all fit into this packet
624                 SDL_assert((wpool_size + spool_size) < 480);
625
626                 // add all ship types
627                 val = (ubyte)spool_size;
628                 ADD_DATA(val);
629                 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
630                         if(Campaign.ships_allowed[idx]){
631                                 val = (ubyte)idx;
632                                 ADD_DATA(val);
633                         }
634                 }               
635
636                 // add all weapon types
637                 val = (ubyte)wpool_size;
638                 ADD_DATA(val);
639                 for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
640                         if(Campaign.weapons_allowed[idx]){
641                                 val = (ubyte)idx;
642                                 ADD_DATA(val);
643                         }
644                 }
645         }
646
647         // send to all players
648         SDL_assert(Net_player->flags & NETINFO_FLAG_AM_MASTER); 
649         multi_io_send_to_all_reliable(data, packet_size);
650
651         // notification message
652         multi_common_add_text(XSTR("Campaign ship/weapon pool\n",644),1);
653 }
654
655 // send a "start campaign" packet
656 void multi_campaign_send_start(net_player *pl)
657 {
658         ubyte data[MAX_PACKET_SIZE],val;
659         int idx;
660         int packet_size = 0;
661
662         // build the header
663         BUILD_HEADER(CAMPAIGN_UPDATE);
664
665         // add the code
666         val = MC_CODE_START;
667         ADD_DATA(val);
668
669         // add the # of missions, and their filenames
670         ADD_INT(Campaign.num_missions);
671         for(idx=0;idx<Campaign.num_missions;idx++){
672                 SDL_assert(Campaign.missions[idx].name != NULL);
673                 ADD_STRING(Campaign.missions[idx].name);
674         }
675
676         // if we're targeting a specific player
677         if(pl != NULL){
678                 multi_io_send_reliable(pl, data, packet_size);
679         }
680         // send to all players
681         else {  
682                 multi_io_send_to_all_reliable(data, packet_size);
683         }
684 }
685
686 // campaign start packet for ingame joiners.  Sends filename and goal/event name and status
687 void multi_campaign_send_ingame_start( net_player *pl )
688 {
689         ubyte data[MAX_PACKET_SIZE], packet_type, num_goals, num_events, *ptr;
690         int packet_size, i, j;
691
692         SDL_assert( pl != NULL );
693         packet_size = 0;
694
695         if ( Game_mode & GM_CAMPAIGN_MODE ) {
696
697                 // first -- add the number of missions and the mission names
698                 // add the # of missions, and their filenames
699                 BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
700                 packet_type = MC_JIP_INITIAL_PACKET;
701                 ADD_DATA(packet_type);
702                 ADD_INT(Campaign.num_missions);
703                 for( i = 0; i < Campaign.num_missions; i++) {
704                         SDL_assert(Campaign.missions[i].name != NULL);
705                         ADD_STRING(Campaign.missions[i].name);
706                 }               
707                 multi_io_send_reliable(pl, data, packet_size);
708
709                 // send the number and status of all goals event for all previous missions
710                 for (i = 0; i < Campaign.num_missions; i++ ) {
711                         ubyte status;
712
713                         // don't send data for the current mission being played, or if both goals and events are 0
714                         SDL_assert( Campaign.missions[i].num_goals < UCHAR_MAX );
715                         SDL_assert( Campaign.missions[i].num_events < UCHAR_MAX );
716                         num_goals = (ubyte)Campaign.missions[i].num_goals;
717                         num_events = (ubyte)Campaign.missions[i].num_events;
718
719                         // don't do anything if mission hasn't been completed
720                         if ( !Campaign.missions[i].completed )
721                                 continue;
722
723                         // add the mission number and the goal/event status
724                         BUILD_HEADER( CAMPAIGN_UPDATE_INGAME );
725                         packet_type = MC_JIP_GE_STATUS;
726                         ADD_DATA( packet_type );
727                         ADD_INT(i);
728                         ADD_DATA( num_goals );
729                         for ( j = 0; j < num_goals; j++ ) {
730                                 status = (ubyte)Campaign.missions[i].goals[j].status;
731                                 ADD_DATA(status);
732                         }
733
734                         // now the events
735                         ADD_DATA( num_events );
736                         for ( j = 0; j < num_events; j++ ) {
737                                 status = (ubyte)Campaign.missions[i].events[j].status;
738                                 ADD_DATA(status);
739                         }
740                         
741                         multi_io_send_reliable(pl, data, packet_size);
742                 }       
743
744                 // send the goal/event names.
745                 for ( i = 0; i < Campaign.num_missions; i++ ) {
746                         ubyte goal_count, starting_goal_num;
747
748                         // first the goal names
749                         SDL_assert( Campaign.missions[i].num_goals < UCHAR_MAX );
750                         num_goals = (ubyte)Campaign.missions[i].num_goals;
751
752                         // don't do anything if mission hasn't been completed
753                         if ( !Campaign.missions[i].completed ){
754                                 continue;
755                         }
756
757                         BUILD_HEADER( CAMPAIGN_UPDATE_INGAME );
758                         packet_type = MC_JIP_GOAL_NAMES;
759                         ADD_DATA(packet_type);
760                         ADD_INT(i);
761
762                         // save a pointer so we can put the number of goals written here.
763                         ptr = &data[packet_size];
764
765                         goal_count = 0;
766                         ADD_DATA( goal_count );
767
768                         starting_goal_num = 0;
769                         ADD_DATA( starting_goal_num );
770
771                         for ( j = 0; j < num_goals; j++ ) {
772                                 ADD_STRING( Campaign.missions[i].goals[j].name );
773                                 goal_count++;
774
775                                 // if packet will get too big, send it off.
776                                 if ( (packet_size + MC_INGAME_DATA_SLOP) > MAX_PACKET_SIZE ) {
777                                         *ptr = goal_count;                                      
778                                         multi_io_send_reliable(pl, data, packet_size);
779                                         BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
780                                         packet_type = MC_JIP_GOAL_NAMES;
781                                         ADD_DATA( packet_type );
782                                         ADD_INT(i);
783                                         ptr = &data[packet_size];
784                                         goal_count = 0;
785                                         ADD_DATA( goal_count );
786                                         starting_goal_num = (ubyte)j;
787                                         ADD_DATA( starting_goal_num );
788                                 }
789                         }
790
791                         *ptr = goal_count;                      
792                         multi_io_send_reliable(pl, data, packet_size);
793                 }
794
795                 // send the goal/event names.
796                 for ( i = 0; i < Campaign.num_missions; i++ ) {
797                         ubyte event_count, starting_event_num;
798
799                         // first the goal names
800                         SDL_assert( Campaign.missions[i].num_events < UCHAR_MAX );
801                         num_events = (ubyte)Campaign.missions[i].num_events;
802
803                         // don't do anything if mission hasn't been completed
804                         if ( !Campaign.missions[i].completed )
805                                 continue;
806
807                         BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
808                         packet_type = MC_JIP_EVENT_NAMES;
809                         ADD_DATA(packet_type);
810                         ADD_INT(i);
811
812                         // save a pointer so we can put the number of goals written here.
813                         ptr = &data[packet_size];
814
815                         event_count = 0;
816                         ADD_DATA( event_count );
817
818                         starting_event_num = 0;
819                         ADD_DATA( starting_event_num );
820
821                         for ( j = 0; j < num_events; j++ ) {
822                                 ADD_STRING( Campaign.missions[i].events[j].name );
823                                 event_count++;
824
825                                 // if packet will get too big, send it off.
826                                 if ( (packet_size + MC_INGAME_DATA_SLOP) > MAX_PACKET_SIZE ) {
827                                         *ptr = event_count;                                     
828                                         multi_io_send_reliable(pl, data, packet_size);
829                                         BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
830                                         packet_type = MC_JIP_EVENT_NAMES;
831                                         ADD_DATA( packet_type );
832                                         ADD_INT(i);
833                                         ptr = &data[packet_size];
834                                         event_count = 0;
835                                         ADD_DATA( event_count );
836                                         starting_event_num = (ubyte)j;
837                                         ADD_DATA( starting_event_num );
838                                 }
839                         }
840
841                         *ptr = event_count;                     
842                         multi_io_send_reliable(pl, data, packet_size);
843                 }
844         }
845
846         // add the stop byte
847         BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
848         packet_type = MC_JIP_END_DATA;
849         ADD_DATA(packet_type);  
850         multi_io_send_reliable(pl, data, packet_size);
851 }
852
853 void multi_campaign_process_ingame_start( ubyte *data, header *hinfo )
854 {
855         int offset, mission_num, i;
856         ubyte packet_type, num_goals, num_events, status, starting_num;
857         char fname[255];
858
859         offset = HEADER_LENGTH;
860
861         GET_DATA( packet_type );
862         switch( packet_type ) {
863         case MC_JIP_INITIAL_PACKET:
864
865                 // clear out the names of the missions
866                 mission_campaign_close();                                               // should free all data structures which need to be freed
867
868                 // get the number of campaigns and their names.
869                 GET_DATA(Campaign.num_missions);
870                 for( i = 0; i < Campaign.num_missions ; i++) {
871                         GET_STRING(fname);
872                         Campaign.missions[i].name = strdup(fname);
873                 }
874
875                 break;
876
877         case MC_JIP_GE_STATUS:
878                 
879                 GET_UINT( mission_num );
880                 GET_DATA( num_goals );
881                 // need to malloc out the data
882                 SDL_assert( Campaign.missions[mission_num].num_goals == 0 );
883                 Campaign.missions[mission_num].num_goals = num_goals;
884                 if ( num_goals > 0 ){
885                         Campaign.missions[mission_num].goals = (mgoal *)malloc( sizeof(mgoal) * num_goals );
886                 }
887                 for ( i = 0; i < num_goals; i++ ) {
888                         GET_DATA(status);
889                         // AL: .goals was a NULL pointer here!  I have no idea why.  Putting
890                         // in a check to avoid the unhandled exception
891                         if ( Campaign.missions[mission_num].goals ) {
892                                 Campaign.missions[mission_num].goals[i].status = status;
893                         }
894                 }
895
896                 // now the events
897                 GET_DATA( num_events );
898                 // need to malloc out the data
899                 SDL_assert( Campaign.missions[mission_num].num_events == 0 );
900                 Campaign.missions[mission_num].num_events = num_events;
901                 if ( num_events > 0 ){
902                         Campaign.missions[mission_num].events = (mevent *)malloc( sizeof(mevent) * num_events );
903                 }
904
905                 for ( i = 0; i < num_events; i++ ) {
906                         GET_DATA(status);
907                         Campaign.missions[mission_num].events[i].status = status;
908                 }
909                 break;
910
911         case MC_JIP_GOAL_NAMES:
912                 GET_UINT( mission_num );
913                 GET_DATA( num_goals );
914                 GET_DATA( starting_num );
915                 for ( i = starting_num; i < (starting_num + num_goals); i++ ) {
916                         GET_STRING(Campaign.missions[mission_num].goals[i].name);
917                 }
918                 break;
919
920         case MC_JIP_EVENT_NAMES:
921                 GET_UINT( mission_num );
922                 GET_DATA( num_events );
923                 GET_DATA( starting_num );
924                 for ( i = starting_num; i < (starting_num + num_events); i++ ) {
925                         GET_STRING(Campaign.missions[mission_num].events[i].name);
926                 }
927                 break;
928
929         case MC_JIP_END_DATA:
930                 Net_player->state = NETPLAYER_STATE_INGAME_CINFO;
931                 send_netplayer_update_packet();
932                 break;
933         }
934
935         PACKET_SET_SIZE();
936 }
937