2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/Network/multi_campaign.cpp $
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 :)
19 * Revision 1.4 2004/06/11 01:16:32 tigital
20 * byte-swapping changes for bigendian systems
22 * Revision 1.3 2002/06/09 04:41:23 relnev
23 * added copyright header
25 * Revision 1.2 2002/05/07 03:16:47 theoddone33
26 * The Great Newline Fix
28 * Revision 1.1.1.1 2002/05/03 03:28:10 root
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.
36 * 5 3/09/99 6:24p Dave
37 * More work on object update revamping. Identified several sources of
38 * unnecessary bandwidth.
40 * 4 12/12/98 3:17p Andsager
41 * Clean up mission eval, goal, event and mission scoring.
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.
47 * 2 10/07/98 10:53a Dave
50 * 1 10/07/98 10:50a Dave
52 * 31 6/13/98 6:01p Hoffoss
53 * Externalized all new (or forgot to be added) strings to all the code.
55 * 30 5/23/98 7:09p Dave
56 * Fixed a potentially serious ingame join campaign bug.
58 * 29 5/23/98 4:28p Jasen
59 * Insure goals pointer is not null.
61 * 28 5/22/98 11:11a Allender
62 * more ingame join campaign fixes
64 * 27 5/21/98 11:34p Allender
67 * 26 5/21/98 2:03a Allender
68 * fix for campaign misison names
70 * 25 5/21/98 12:14a Allender
71 * fix ingame join problems
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
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.
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.
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.
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)
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.
98 * 18 5/05/98 2:10p Dave
99 * Verify campaign support for testing. More new tracker code.
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.
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.
110 * 15 4/20/98 4:56p Allender
111 * allow AI ships to respawn as many times as there are respawns in the
114 * 14 4/06/98 10:24p Dave
115 * Fixed up Netgame.respawn for the standalone case.
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
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.
129 * 11 3/17/98 12:16a Allender
130 * asteroids in multiplayer -- minor problems with position being correct
132 * 10 3/16/98 2:35p Dave
133 * Numerous bug fixes. Made the "cue sound" sound play before incoming
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.
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
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.
149 * 6 3/05/98 5:03p Dave
150 * More work on team vs. team support for multiplayer. Need to fix bugs in
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.
157 * 4 2/23/98 11:09p Dave
158 * Finished up multiplayer campaign support. Seems bug-free.
160 * 3 2/23/98 5:08p Allender
161 * made net_signature an unsigned short. Now using permanent and
162 * non-permanent object "pools".
164 * 2 2/22/98 2:53p Dave
165 * Put in groundwork for advanced multiplayer campaign options.
167 * 1 2/20/98 4:39p Dave
168 * Split up mp campaign functionality into its own module.
175 #include "gamesequence.h"
178 #include "freespace.h"
179 #include "multimsgs.h"
180 #include "multiutil.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"
188 // ------------------------------------------------------------------------------------
189 // MULTIPLAYER CAMPAIGN DEFINES/VARS
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
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
206 #define MC_INGAME_DATA_SLOP 50
209 // flags indicating the "accept" status of all players involved in a campaign
210 int Multi_campaign_accept_flags[MAX_PLAYERS];
213 // ------------------------------------------------------------------------------------
214 // MULTIPLAYER CAMPAIGN FUNCTIONS
217 // load a new campaign file or notify the standalone if we're not the server
218 void multi_campaign_start(char *filename)
223 // set the netgame mode
224 Netgame.campaign_mode = MP_CAMPAIGN;
226 // set the campaign filename
227 SDL_strlcpy(Netgame.campaign_name, filename, SDL_arraysize(Netgame.campaign_name));
229 // add the campaign mode flag
230 Game_mode |= GM_CAMPAIGN_MODE;
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
236 mission_campaign_load(filename);
237 mission_campaign_next_mission();
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));
244 // if we're the standalone server, set the mission and campaign names
245 if(Game_mode & GM_STANDALONE_SERVER){
247 SDL_snprintf(str, SDL_arraysize(str), "%s (%s)", Netgame.mission_name,Netgame.campaign_name );
249 // set the control on the stand_gui
250 std_multi_set_standalone_mission_name(str);
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));
258 // send a "start campaign" packet
259 multi_campaign_send_start();
263 // client-side start of a campaign
264 void multi_campaign_client_start()
266 memset(&Campaign,0,sizeof(Campaign));
268 // set campaign mode. what the hell.
269 Game_mode |= GM_CAMPAIGN_MODE;
272 // move everything and eveyrone into the next mission state
273 void multi_campaign_next_mission()
277 // flush the important data
278 multi_campaign_flush_data();
280 // call the campaign over function
281 mission_campaign_mission_over();
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));
289 // if we're the standalone server, set the mission and campaign names
290 if(Game_mode & GM_STANDALONE_SERVER){
292 SDL_snprintf(str, SDL_arraysize(str), "%s (%s)", Netgame.mission_name, Netgame.campaign_name);
294 // set the control on the stand_gui
295 std_multi_set_standalone_mission_name(str);
301 // flush all important data between missions
302 void multi_campaign_flush_data()
304 // blast the accept flags
305 memset(Multi_campaign_accept_flags,0,sizeof(int) * MAX_PLAYERS);
307 // flush mission stuff
308 multi_flush_mission_stuff();
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)
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();
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();
330 if(Game_mode & GM_STANDALONE_SERVER){
331 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
333 gameseq_post_event(GS_EVENT_MULTI_HOST_SETUP);
335 multi_reset_timestamps();
337 // if we're still in the campaign
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();
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();
353 Multi_sync_mode = MULTI_SYNC_PRE_BRIEFING;
354 gameseq_post_event(GS_EVENT_MULTI_MISSION_SYNC);
356 multi_reset_timestamps();
363 // display the done popup
364 void multi_campaign_done_popup()
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);
370 // evaluate post mission goal stuff for the campaign and send all relevant stuff to clients
371 void multi_campaign_eval_debrief()
373 // evaluate mission stuff (fills in structures, etc).
374 // DKA 12/12/98 already done
375 // mission_campaign_eval_next_mission();
377 // send the campaign debriefing packet
378 multi_campaign_send_debrief_info();
381 // clients should store mission goal/event names in the campaign now
382 void multi_campaign_client_store_goals(int mission_num)
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);
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);
398 // ------------------------------------------------------------------------------------
399 // MULTIPLAYER CAMPAIGN PACKET HANDLERS
402 // process a campaign update packet
403 void multi_campaign_process_update(ubyte *data, header *hinfo)
405 int offset = HEADER_LENGTH;
407 ubyte val,spool_size,wpool_size;
409 ubyte cur_mission,next_mission;
412 // get the packet code
417 // display the done popup
418 multi_campaign_done_popup();
422 // get the campaign status byte
425 // if we're not in campaign mode, bash all weapons and ships to be "allowed"
428 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
429 Campaign.ships_allowed[idx] = 1;
433 for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
434 Campaign.weapons_allowed[idx] = 1;
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);
441 // get all ship classes
442 GET_DATA(spool_size);
443 for(idx=0;idx<spool_size;idx++){
445 Campaign.ships_allowed[val] = 1;
448 // get all weapon classes
449 GET_DATA(wpool_size);
450 for(idx=0;idx<wpool_size;idx++){
452 Campaign.weapons_allowed[val] = 1;
457 Net_player->state = NETPLAYER_STATE_CPOOL_ACK;
458 send_netplayer_update_packet();
461 case MC_CODE_DEBRIEF:
462 GET_DATA(cur_mission);
463 GET_DATA(next_mission);
467 Campaign.missions[cur_mission].name = strdup(fname);
469 // add the # of goals and events
471 Campaign.missions[cur_mission].num_goals = val;
472 Campaign.missions[cur_mission].goals = (mgoal*)malloc(sizeof(mgoal) * val);
475 Campaign.missions[cur_mission].num_events = val;
476 Campaign.missions[cur_mission].events = (mevent*)malloc(sizeof(mevent) * val);
479 for(idx=0;idx<Campaign.missions[cur_mission].num_goals;idx++){
481 Campaign.missions[cur_mission].goals[idx].status = val;
485 for(idx=0;idx<Campaign.missions[cur_mission].num_events;idx++){
487 Campaign.missions[cur_mission].events[idx].status = val;
490 // now set the "next mission to be the "current mission"
491 Campaign.prev_mission = cur_mission;
492 Campaign.current_mission = next_mission;
494 // clients should store mission goal/event names in the campaign now
495 multi_campaign_client_store_goals(cur_mission);
499 // clear the campaign
500 multi_campaign_client_start();
502 // read in the # of missions
503 GET_INT(Campaign.num_missions);
505 // read in the mission filenames
506 for(idx=0;idx<Campaign.num_missions;idx++){
508 Campaign.missions[idx].name = strdup(fname);
516 // send a "campaign finished" packet
517 void multi_campaign_send_done()
523 BUILD_HEADER(CAMPAIGN_UPDATE);
529 // broadcast the packet
530 multi_io_send_to_all_reliable(data, packet_size);
533 // send a campaign debrief update packet
534 void multi_campaign_send_debrief_info()
536 ubyte data[MAX_PACKET_SIZE],val;
541 BUILD_HEADER(CAMPAIGN_UPDATE);
544 val = MC_CODE_DEBRIEF;
547 // add the mission # we're including
548 val = (ubyte)Campaign.current_mission;
551 // add the next mission
552 val = (ubyte)Campaign.next_mission;
556 SDL_assert(Campaign.missions[Campaign.current_mission].name != NULL);
557 ADD_STRING(Campaign.missions[Campaign.current_mission].name);
559 // add the # of goals and events
560 val = (ubyte)Campaign.missions[Campaign.current_mission].num_goals;
562 val = (ubyte)Campaign.missions[Campaign.current_mission].num_events;
566 for(idx=0;idx<Campaign.missions[Campaign.current_mission].num_goals;idx++){
567 val = (ubyte)Campaign.missions[Campaign.current_mission].goals[idx].status;
572 for(idx=0;idx<Campaign.missions[Campaign.current_mission].num_events;idx++){
573 val = (ubyte)Campaign.missions[Campaign.current_mission].events[idx].status;
577 // send to all players
578 multi_io_send_to_all_reliable(data, packet_size);
581 // send a campaign pool status packet
582 void multi_campaign_send_pool_status()
584 ubyte data[MAX_PACKET_SIZE],val;
591 BUILD_HEADER(CAMPAIGN_UPDATE);
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)){
602 // otherwise add all relevant ship/weapon pool data
607 // determine how many ship types we're going to add
609 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
610 if(Campaign.ships_allowed[idx]){
615 // determine how many weapon types we're going to add
617 for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
618 if(Campaign.weapons_allowed[idx]){
623 // make sure it'll all fit into this packet
624 SDL_assert((wpool_size + spool_size) < 480);
626 // add all ship types
627 val = (ubyte)spool_size;
629 for(idx=0;idx<MAX_SHIP_TYPES;idx++){
630 if(Campaign.ships_allowed[idx]){
636 // add all weapon types
637 val = (ubyte)wpool_size;
639 for(idx=0;idx<MAX_WEAPON_TYPES;idx++){
640 if(Campaign.weapons_allowed[idx]){
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);
651 // notification message
652 multi_common_add_text(XSTR("Campaign ship/weapon pool\n",644),1);
655 // send a "start campaign" packet
656 void multi_campaign_send_start(net_player *pl)
658 ubyte data[MAX_PACKET_SIZE],val;
663 BUILD_HEADER(CAMPAIGN_UPDATE);
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);
676 // if we're targeting a specific player
678 multi_io_send_reliable(pl, data, packet_size);
680 // send to all players
682 multi_io_send_to_all_reliable(data, packet_size);
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 )
689 ubyte data[MAX_PACKET_SIZE], packet_type, num_goals, num_events, *ptr;
690 int packet_size, i, j;
692 SDL_assert( pl != NULL );
695 if ( Game_mode & GM_CAMPAIGN_MODE ) {
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);
707 multi_io_send_reliable(pl, data, packet_size);
709 // send the number and status of all goals event for all previous missions
710 for (i = 0; i < Campaign.num_missions; i++ ) {
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;
719 // don't do anything if mission hasn't been completed
720 if ( !Campaign.missions[i].completed )
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 );
728 ADD_DATA( num_goals );
729 for ( j = 0; j < num_goals; j++ ) {
730 status = (ubyte)Campaign.missions[i].goals[j].status;
735 ADD_DATA( num_events );
736 for ( j = 0; j < num_events; j++ ) {
737 status = (ubyte)Campaign.missions[i].events[j].status;
741 multi_io_send_reliable(pl, data, packet_size);
744 // send the goal/event names.
745 for ( i = 0; i < Campaign.num_missions; i++ ) {
746 ubyte goal_count, starting_goal_num;
748 // first the goal names
749 SDL_assert( Campaign.missions[i].num_goals < UCHAR_MAX );
750 num_goals = (ubyte)Campaign.missions[i].num_goals;
752 // don't do anything if mission hasn't been completed
753 if ( !Campaign.missions[i].completed ){
757 BUILD_HEADER( CAMPAIGN_UPDATE_INGAME );
758 packet_type = MC_JIP_GOAL_NAMES;
759 ADD_DATA(packet_type);
762 // save a pointer so we can put the number of goals written here.
763 ptr = &data[packet_size];
766 ADD_DATA( goal_count );
768 starting_goal_num = 0;
769 ADD_DATA( starting_goal_num );
771 for ( j = 0; j < num_goals; j++ ) {
772 ADD_STRING( Campaign.missions[i].goals[j].name );
775 // if packet will get too big, send it off.
776 if ( (packet_size + MC_INGAME_DATA_SLOP) > MAX_PACKET_SIZE ) {
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 );
783 ptr = &data[packet_size];
785 ADD_DATA( goal_count );
786 starting_goal_num = (ubyte)j;
787 ADD_DATA( starting_goal_num );
792 multi_io_send_reliable(pl, data, packet_size);
795 // send the goal/event names.
796 for ( i = 0; i < Campaign.num_missions; i++ ) {
797 ubyte event_count, starting_event_num;
799 // first the goal names
800 SDL_assert( Campaign.missions[i].num_events < UCHAR_MAX );
801 num_events = (ubyte)Campaign.missions[i].num_events;
803 // don't do anything if mission hasn't been completed
804 if ( !Campaign.missions[i].completed )
807 BUILD_HEADER(CAMPAIGN_UPDATE_INGAME);
808 packet_type = MC_JIP_EVENT_NAMES;
809 ADD_DATA(packet_type);
812 // save a pointer so we can put the number of goals written here.
813 ptr = &data[packet_size];
816 ADD_DATA( event_count );
818 starting_event_num = 0;
819 ADD_DATA( starting_event_num );
821 for ( j = 0; j < num_events; j++ ) {
822 ADD_STRING( Campaign.missions[i].events[j].name );
825 // if packet will get too big, send it off.
826 if ( (packet_size + MC_INGAME_DATA_SLOP) > MAX_PACKET_SIZE ) {
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 );
833 ptr = &data[packet_size];
835 ADD_DATA( event_count );
836 starting_event_num = (ubyte)j;
837 ADD_DATA( starting_event_num );
842 multi_io_send_reliable(pl, data, packet_size);
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);
853 void multi_campaign_process_ingame_start( ubyte *data, header *hinfo )
855 int offset, mission_num, i;
856 ubyte packet_type, num_goals, num_events, status, starting_num;
859 offset = HEADER_LENGTH;
861 GET_DATA( packet_type );
862 switch( packet_type ) {
863 case MC_JIP_INITIAL_PACKET:
865 // clear out the names of the missions
866 mission_campaign_close(); // should free all data structures which need to be freed
868 // get the number of campaigns and their names.
869 GET_DATA(Campaign.num_missions);
870 for( i = 0; i < Campaign.num_missions ; i++) {
872 Campaign.missions[i].name = strdup(fname);
877 case MC_JIP_GE_STATUS:
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 );
887 for ( i = 0; i < num_goals; i++ ) {
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;
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 );
905 for ( i = 0; i < num_events; i++ ) {
907 Campaign.missions[mission_num].events[i].status = status;
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);
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);
929 case MC_JIP_END_DATA:
930 Net_player->state = NETPLAYER_STATE_INGAME_CINFO;
931 send_netplayer_update_packet();