2 * $Logfile: /Freespace2/code/Network/multi_campaign.cpp $
8 * Revision 1.2 2002/05/07 03:16:47 theoddone33
9 * The Great Newline Fix
11 * Revision 1.1.1.1 2002/05/03 03:28:10 root
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.
19 * 5 3/09/99 6:24p Dave
20 * More work on object update revamping. Identified several sources of
21 * unnecessary bandwidth.
23 * 4 12/12/98 3:17p Andsager
24 * Clean up mission eval, goal, event and mission scoring.
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.
30 * 2 10/07/98 10:53a Dave
33 * 1 10/07/98 10:50a Dave
35 * 31 6/13/98 6:01p Hoffoss
36 * Externalized all new (or forgot to be added) strings to all the code.
38 * 30 5/23/98 7:09p Dave
39 * Fixed a potentially serious ingame join campaign bug.
41 * 29 5/23/98 4:28p Jasen
42 * Insure goals pointer is not null.
44 * 28 5/22/98 11:11a Allender
45 * more ingame join campaign fixes
47 * 27 5/21/98 11:34p Allender
50 * 26 5/21/98 2:03a Allender
51 * fix for campaign misison names
53 * 25 5/21/98 12:14a Allender
54 * fix ingame join problems
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
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.
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.
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.
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)
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.
81 * 18 5/05/98 2:10p Dave
82 * Verify campaign support for testing. More new tracker code.
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.
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.
93 * 15 4/20/98 4:56p Allender
94 * allow AI ships to respawn as many times as there are respawns in the
97 * 14 4/06/98 10:24p Dave
98 * Fixed up Netgame.respawn for the standalone case.
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
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.
112 * 11 3/17/98 12:16a Allender
113 * asteroids in multiplayer -- minor problems with position being correct
115 * 10 3/16/98 2:35p Dave
116 * Numerous bug fixes. Made the "cue sound" sound play before incoming
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.
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
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.
132 * 6 3/05/98 5:03p Dave
133 * More work on team vs. team support for multiplayer. Need to fix bugs in
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.
140 * 4 2/23/98 11:09p Dave
141 * Finished up multiplayer campaign support. Seems bug-free.
143 * 3 2/23/98 5:08p Allender
144 * made net_signature an unsigned short. Now using permanent and
145 * non-permanent object "pools".
147 * 2 2/22/98 2:53p Dave
148 * Put in groundwork for advanced multiplayer campaign options.
150 * 1 2/20/98 4:39p Dave
151 * Split up mp campaign functionality into its own module.
158 #include "gamesequence.h"
161 #include "freespace.h"
162 #include "multimsgs.h"
163 #include "multiutil.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"
171 // ------------------------------------------------------------------------------------
172 // MULTIPLAYER CAMPAIGN DEFINES/VARS
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
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
189 #define MC_INGAME_DATA_SLOP 50
192 // flags indicating the "accept" status of all players involved in a campaign
193 int Multi_campaign_accept_flags[MAX_PLAYERS];
196 // ------------------------------------------------------------------------------------
197 // MULTIPLAYER CAMPAIGN FUNCTIONS
200 // load a new campaign file or notify the standalone if we're not the server
201 void multi_campaign_start(char *filename)
206 // set the netgame mode
207 Netgame.campaign_mode = MP_CAMPAIGN;
209 // set the campaign filename
210 strcpy(Netgame.campaign_name,filename);
212 // add the campaign mode flag
213 Game_mode |= GM_CAMPAIGN_MODE;
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
219 mission_campaign_load(filename);
220 mission_campaign_next_mission();
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);
227 // if we're the standalone server, set the mission and campaign names
228 if(Game_mode & GM_STANDALONE_SERVER){
230 strcpy(str,Netgame.mission_name);
232 strcat(str,Netgame.campaign_name);
235 // set the control on the stand_gui
236 std_multi_set_standalone_mission_name(str);
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));
244 // send a "start campaign" packet
245 multi_campaign_send_start();
249 // client-side start of a campaign
250 void multi_campaign_client_start()
252 memset(&Campaign,0,sizeof(Campaign));
254 // set campaign mode. what the hell.
255 Game_mode |= GM_CAMPAIGN_MODE;
258 // move everything and eveyrone into the next mission state
259 void multi_campaign_next_mission()
263 // flush the important data
264 multi_campaign_flush_data();
266 // call the campaign over function
267 mission_campaign_mission_over();
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);
275 // if we're the standalone server, set the mission and campaign names
276 if(Game_mode & GM_STANDALONE_SERVER){
278 strcpy(str,Netgame.mission_name);
280 strcat(str,Netgame.campaign_name);
283 // set the control on the stand_gui
284 std_multi_set_standalone_mission_name(str);
290 // flush all important data between missions
291 void multi_campaign_flush_data()
293 // blast the accept flags
294 memset(Multi_campaign_accept_flags,0,sizeof(int) * MAX_PLAYERS);
296 // flush mission stuff
297 multi_flush_mission_stuff();
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)
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();
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();
319 if(Game_mode & GM_STANDALONE_SERVER){
320 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
322 gameseq_post_event(GS_EVENT_MULTI_HOST_SETUP);
324 multi_reset_timestamps();
326 // if we're still in the campaign
328 Netgame.game_state = NETGAME_STATE_MISSION_SYNC;
329 send_netgame_update_packet();
331 Multi_sync_mode = MULTI_SYNC_PRE_BRIEFING;
332 gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC);
334 multi_reset_timestamps();
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();
342 Multi_sync_mode = MULTI_SYNC_PRE_BRIEFING;
343 gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC);
345 multi_reset_timestamps();
352 // display the done popup
353 void multi_campaign_done_popup()
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);
359 // evaluate post mission goal stuff for the campaign and send all relevant stuff to clients
360 void multi_campaign_eval_debrief()
362 // evaluate mission stuff (fills in structures, etc).
363 // DKA 12/12/98 already done
364 // mission_campaign_eval_next_mission();
366 // send the campaign debriefing packet
367 multi_campaign_send_debrief_info();
370 // clients should store mission goal/event names in the campaign now
371 void multi_campaign_client_store_goals(int mission_num)
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);
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);
387 // ------------------------------------------------------------------------------------
388 // MULTIPLAYER CAMPAIGN PACKET HANDLERS
391 // process a campaign update packet
392 void multi_campaign_process_update(ubyte *data, header *hinfo)
394 int offset = HEADER_LENGTH;
396 ubyte val,spool_size,wpool_size;
398 ubyte cur_mission,next_mission;
401 // get the packet code
406 // display the done popup
407 multi_campaign_done_popup();
411 // get the campaign status byte
414 // if we're not in campaign mode, bash all weapons and ships to be "allowed"
417 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
418 Campaign.ships_allowed[idx] = 1;
422 for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
423 Campaign.weapons_allowed[idx] = 1;
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);
430 // get all ship classes
431 GET_DATA(spool_size);
432 for(idx=0;idx<spool_size;idx++){
434 Campaign.ships_allowed[val] = 1;
437 // get all weapon classes
438 GET_DATA(wpool_size);
439 for(idx=0;idx<wpool_size;idx++){
441 Campaign.weapons_allowed[val] = 1;
446 Net_player->state = NETPLAYER_STATE_CPOOL_ACK;
447 send_netplayer_update_packet();
450 case MC_CODE_DEBRIEF:
451 GET_DATA(cur_mission);
452 GET_DATA(next_mission);
456 Campaign.missions[cur_mission].name = strdup(fname);
458 // add the # of goals and events
460 Campaign.missions[cur_mission].num_goals = val;
461 Campaign.missions[cur_mission].goals = (mgoal*)malloc(sizeof(mgoal) * val);
464 Campaign.missions[cur_mission].num_events = val;
465 Campaign.missions[cur_mission].events = (mevent*)malloc(sizeof(mevent) * val);
468 for(idx=0;idx<Campaign.missions[cur_mission].num_goals;idx++){
470 Campaign.missions[cur_mission].goals[idx].status = val;
474 for(idx=0;idx<Campaign.missions[cur_mission].num_events;idx++){
476 Campaign.missions[cur_mission].events[idx].status = val;
479 // now set the "next mission to be the "current mission"
480 Campaign.prev_mission = cur_mission;
481 Campaign.current_mission = next_mission;
483 // clients should store mission goal/event names in the campaign now
484 multi_campaign_client_store_goals(cur_mission);
488 // clear the campaign
489 multi_campaign_client_start();
491 // read in the # of missions
492 GET_DATA(Campaign.num_missions);
494 // read in the mission filenames
495 for(idx=0;idx<Campaign.num_missions;idx++){
497 Campaign.missions[idx].name = strdup(fname);
505 // send a "campaign finished" packet
506 void multi_campaign_send_done()
512 BUILD_HEADER(CAMPAIGN_UPDATE);
518 // broadcast the packet
519 multi_io_send_to_all_reliable(data, packet_size);
522 // send a campaign debrief update packet
523 void multi_campaign_send_debrief_info()
525 ubyte data[MAX_PACKET_SIZE],val;
530 BUILD_HEADER(CAMPAIGN_UPDATE);
533 val = MC_CODE_DEBRIEF;
536 // add the mission # we're including
537 val = (ubyte)Campaign.current_mission;
540 // add the next mission
541 val = (ubyte)Campaign.next_mission;
545 Assert(Campaign.missions[Campaign.current_mission].name != NULL);
546 ADD_STRING(Campaign.missions[Campaign.current_mission].name);
548 // add the # of goals and events
549 val = (ubyte)Campaign.missions[Campaign.current_mission].num_goals;
551 val = (ubyte)Campaign.missions[Campaign.current_mission].num_events;
555 for(idx=0;idx<Campaign.missions[Campaign.current_mission].num_goals;idx++){
556 val = (ubyte)Campaign.missions[Campaign.current_mission].goals[idx].status;
561 for(idx=0;idx<Campaign.missions[Campaign.current_mission].num_events;idx++){
562 val = (ubyte)Campaign.missions[Campaign.current_mission].events[idx].status;
566 // send to all players
567 multi_io_send_to_all_reliable(data, packet_size);
570 // send a campaign pool status packet
571 void multi_campaign_send_pool_status()
573 ubyte data[MAX_PACKET_SIZE],val;
580 BUILD_HEADER(CAMPAIGN_UPDATE);
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)){
591 // otherwise add all relevant ship/weapon pool data
596 // determine how many ship types we're going to add
598 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
599 if(Campaign.ships_allowed[idx]){
604 // determine how many weapon types we're going to add
606 for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
607 if(Campaign.weapons_allowed[idx]){
612 // make sure it'll all fit into this packet
613 Assert((wpool_size + spool_size) < 480);
615 // add all ship types
616 val = (ubyte)spool_size;
618 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
619 if(Campaign.ships_allowed[idx]){
625 // add all weapon types
626 val = (ubyte)wpool_size;
628 for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
629 if(Campaign.weapons_allowed[idx]){
636 // send to all players
637 Assert(Net_player->flags & NETINFO_FLAG_AM_MASTER);
638 multi_io_send_to_all_reliable(data, packet_size);
640 // notification message
641 multi_common_add_text(XSTR("Campaign ship/weapon pool\n",644),1);
644 // send a "start campaign" packet
645 void multi_campaign_send_start(net_player *pl)
647 ubyte data[MAX_PACKET_SIZE],val;
652 BUILD_HEADER(CAMPAIGN_UPDATE);
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);
665 // if we're targeting a specific player
667 multi_io_send_reliable(pl, data, packet_size);
669 // send to all players
671 multi_io_send_to_all_reliable(data, packet_size);
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 )
678 ubyte data[MAX_PACKET_SIZE], packet_type, num_goals, num_events, *ptr;
679 int packet_size, i, j;
681 Assert( pl != NULL );
684 if ( Game_mode & GM_CAMPAIGN_MODE ) {
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);
696 multi_io_send_reliable(pl, data, packet_size);
698 // send the number and status of all goals event for all previous missions
699 for (i = 0; i < Campaign.num_missions; i++ ) {
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;
708 // don't do anything if mission hasn't been completed
709 if ( !Campaign.missions[i].completed )
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 );
717 ADD_DATA( num_goals );
718 for ( j = 0; j < num_goals; j++ ) {
719 status = (ubyte)Campaign.missions[i].goals[j].status;
724 ADD_DATA( num_events );
725 for ( j = 0; j < num_events; j++ ) {
726 status = (ubyte)Campaign.missions[i].events[j].status;
730 multi_io_send_reliable(pl, data, packet_size);
733 // send the goal/event names.
734 for ( i = 0; i < Campaign.num_missions; i++ ) {
735 ubyte goal_count, starting_goal_num;
737 // first the goal names
738 Assert( Campaign.missions[i].num_goals < UCHAR_MAX );
739 num_goals = (ubyte)Campaign.missions[i].num_goals;
741 // don't do anything if mission hasn't been completed
742 if ( !Campaign.missions[i].completed ){
746 BUILD_HEADER( CAMPAIGN_UPDATE_INGAME );
747 packet_type = MC_JIP_GOAL_NAMES;
748 ADD_DATA(packet_type);
751 // save a pointer so we can put the number of goals written here.
752 ptr = &data[packet_size];
755 ADD_DATA( goal_count );
757 starting_goal_num = 0;
758 ADD_DATA( starting_goal_num );
760 for ( j = 0; j < num_goals; j++ ) {
761 ADD_STRING( Campaign.missions[i].goals[j].name );
764 // if packet will get too big, send it off.
765 if ( (packet_size + MC_INGAME_DATA_SLOP) > MAX_PACKET_SIZE ) {
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 );
772 ptr = &data[packet_size];
774 ADD_DATA( goal_count );
775 starting_goal_num = (ubyte)j;
776 ADD_DATA( starting_goal_num );
781 multi_io_send_reliable(pl, data, packet_size);
784 // send the goal/event names.
785 for ( i = 0; i < Campaign.num_missions; i++ ) {
786 ubyte event_count, starting_event_num;
788 // first the goal names
789 Assert( Campaign.missions[i].num_events < UCHAR_MAX );
790 num_events = (ubyte)Campaign.missions[i].num_events;
792 // don't do anything if mission hasn't been completed
793 if ( !Campaign.missions[i].completed )
796 BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
797 packet_type = MC_JIP_EVENT_NAMES;
798 ADD_DATA(packet_type);
801 // save a pointer so we can put the number of goals written here.
802 ptr = &data[packet_size];
805 ADD_DATA( event_count );
807 starting_event_num = 0;
808 ADD_DATA( starting_event_num );
810 for ( j = 0; j < num_events; j++ ) {
811 ADD_STRING( Campaign.missions[i].events[j].name );
814 // if packet will get too big, send it off.
815 if ( (packet_size + MC_INGAME_DATA_SLOP) > MAX_PACKET_SIZE ) {
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 );
822 ptr = &data[packet_size];
824 ADD_DATA( event_count );
825 starting_event_num = (ubyte)j;
826 ADD_DATA( starting_event_num );
831 multi_io_send_reliable(pl, data, packet_size);
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);
842 void multi_campaign_process_ingame_start( ubyte *data, header *hinfo )
844 int offset, mission_num, i;
845 ubyte packet_type, num_goals, num_events, status, starting_num;
848 offset = HEADER_LENGTH;
850 GET_DATA( packet_type );
851 switch( packet_type ) {
852 case MC_JIP_INITIAL_PACKET:
854 // clear out the names of the missions
855 mission_campaign_close(); // should free all data structures which need to be freed
857 // get the number of campaigns and their names.
858 GET_DATA(Campaign.num_missions);
859 for( i = 0; i < Campaign.num_missions ; i++) {
861 Campaign.missions[i].name = strdup(fname);
866 case MC_JIP_GE_STATUS:
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 );
876 for ( i = 0; i < num_goals; i++ ) {
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;
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 );
894 for ( i = 0; i < num_events; i++ ) {
896 Campaign.missions[mission_num].events[i].status = status;
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);
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);
918 case MC_JIP_END_DATA:
919 Net_player->state = NETPLAYER_STATE_INGAME_CINFO;
920 send_netplayer_update_packet();