// close void multi_df_debrief_close() { int idx; scoring_struct *sc; // shutdown the chatbox chatbox_close(); // if stats weren't accepted, backout my own stats if (multi_debrief_stats_accept_code() != 1) { // if stats weren't accepted, backout my own stats if (multi_debrief_stats_accept_code() != 1) { if(MULTIPLAYER_MASTER){ for(idx=0; idx<MAX_PLAYERS; idx++){ if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) && (Net_players[idx].m_player != NULL)){ sc = &Net_players[idx].m_player->stats; scoring_backout_accept(sc); if (Net_player == &Net_players[idx]) { Pilot.update_stats_backout( sc ); } } } } else { scoring_backout_accept( &Player->stats ); Pilot.update_stats_backout( &Player->stats ); } } } // music stuff common_music_close(); }
// merge any mission stats accumulated into the alltime stats (as well as updating per campaign stats) void scoring_level_close(int accepted) { // want to calculate any other statistics. if (The_mission.game_type == MISSION_TYPE_TRAINING){ // call scoring_do_accept // this will grant any potential medals and then early bail, and // then we will early bail scoring_do_accept(&Player->stats); Pilot.update_stats(&Player->stats, true); return; } if(accepted){ // apply mission stats for all players in the game int idx; scoring_struct *sc; if(Game_mode & GM_MULTIPLAYER){ nprintf(("Network","Storing stats for all players now\n")); for(idx=0;idx<MAX_PLAYERS;idx++){ if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){ // get the scoring struct sc = &Net_players[idx].m_player->stats; scoring_do_accept( sc ); if (Net_player == &Net_players[idx]) { Pilot.update_stats(sc); } } } } else { nprintf(("General","Storing stats now\n")); scoring_do_accept( &Player->stats ); } // If this mission doesn't allow promotion or badges // then be sure that these don't get done. Don't allow promotions or badges when // playing normally and not in a campaign. if ( (The_mission.flags & MISSION_FLAG_NO_PROMOTION) || ((Game_mode & GM_NORMAL) && !(Game_mode & GM_CAMPAIGN_MODE)) ) { if ( Player->stats.m_promotion_earned != -1) { Player->stats.rank--; Player->stats.m_promotion_earned = -1; } // if a badge was earned, take it back if ( Player->stats.m_badge_earned.size() ){ for (size_t medal = 0; medal < Player->stats.m_badge_earned.size(); medal++) { Player->stats.medal_counts[Player->stats.m_badge_earned[medal]] = 0; } Player->stats.m_badge_earned.clear(); } } if ( !(Game_mode & GM_MULTIPLAYER) ) { Pilot.update_stats(&Player->stats); } } }
void hud_obs_render_players_all() { int idx,count; // render kills and stats information for all players count = 0; for(idx=0;idx<MAX_PLAYERS;idx++){ if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) ){ hud_obs_render_player(count,&Net_players[idx]); } } }
// evaluate if a wing SQUADMATE MESSAGE command should be sent to a player // return 0 if at least one ai ship got the order, 1 if only players int multi_msg_eval_wing_squadmsg(int wingnum,int command,ai_info *aif, int player_num) { int idx; ushort net_sig; int subsys_type; int sent_count; // get the index of the sender if(player_num == -1) player_num = MY_NET_PLAYER_NUM; // get the target information if(aif->target_objnum == -1){ net_sig = 0; } else { net_sig = Objects[aif->target_objnum].net_signature; } subsys_type = -1; if((aif->targeted_subsys == NULL) || (aif->targeted_subsys->system_info == NULL)){ subsys_type = -1; } else { subsys_type = aif->targeted_subsys->system_info->type; } // go through all netplayers and find all matched sent_count = Wings[wingnum].current_count; for(idx=0;idx<MAX_PLAYERS;idx++){ if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){ // if he is in the wing, send him the message if(multi_msg_player_in_wing(wingnum,&Net_players[idx])){ // if this was the sender himself, just decrement the count if(idx == player_num){ sent_count--; continue; } // if its me, just display locally if(&Net_players[idx] == Net_player){ multi_msg_show_squadmsg(&Net_players[player_num],command,net_sig,subsys_type); sent_count--; } // otherwise send it to who is supposed to get it else { multi_msg_send_squadmsg_packet(&Net_players[idx],&Net_players[player_num],command,net_sig,subsys_type); sent_count--; } } } } // if all the ships which got the message were players, return 1 return !sent_count; }
// display ingame,inmission message text void multi_msg_display_mission_text(const char *msg, int player_index) { // play a cue voice sound and text to speech if not from this player if(Net_players[player_index].player_id != MY_NET_PLAYER_NUM) { snd_play(&Snds[MULTI_MSG_TEXT_SOUND]); fsspeech_play(FSSPEECH_FROM_MULTI, msg); } if(MULTI_STANDALONE(Net_players[player_index])){ HUD_sourced_printf(HUD_SOURCE_NETPLAYER,"%s %s",XSTR("<SERVER>", 698), msg); } else { HUD_sourced_printf(HUD_SOURCE_NETPLAYER,"%s: %s", Net_players[player_index].m_player->callsign, msg); } }
// evaluate if a ship SQUADMATE MESSAGE command should be sent to a player // return 0 if not sent to a netplayer, 1 if it was int multi_msg_eval_ship_squadmsg(int shipnum,int command,ai_info *aif, int player_num) { int idx; ushort net_sig; int subsys_type; // get the index of the sender if ( player_num == -1 ) player_num = MY_NET_PLAYER_NUM; // get the target information if(aif->target_objnum == -1){ net_sig = 0; } else { net_sig = Objects[aif->target_objnum].net_signature; } subsys_type = -1; if((aif->targeted_subsys == NULL) || (aif->targeted_subsys->system_info == NULL)){ subsys_type = -1; } else { subsys_type = aif->targeted_subsys->system_info->type; } // go through all netplayers and find all matched for(idx=0;idx<MAX_PLAYERS;idx++){ if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (idx != player_num)){ // if he is in the ship, send him the message if(multi_msg_player_in_ship(shipnum,&Net_players[idx])){ // if its me, just display locall if(&Net_players[idx] == Net_player){ multi_msg_show_squadmsg(&Net_players[player_num],command,net_sig,subsys_type); return 1; } // otherwise send it to who is supposed to get it else { multi_msg_send_squadmsg_packet(&Net_players[idx],&Net_players[player_num],command,net_sig,subsys_type); return 1; } } } } // this will let the messaging system show a response to the sender of the packet return 0; }
void FS2NetD_CheckDuplicateLogin() { int buffer_size; char buffer[BASE_PACKET_SIZE + sizeof(int) + sizeof(ubyte) + (MAX_PLAYERS * sizeof(int)) + 10]; int ids_count = 0; int *ids = new int[MAX_PLAYERS]; int idx; if ( !ids ) { return; } for (idx = 0; idx < MAX_PLAYERS; idx++) { if ( MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) ) { if ( (Net_players[idx].tracker_player_id >= 0) && (Net_players[idx].tracker_player_id != Multi_tracker_id) ) { ids[ids_count] = Net_players[idx].tracker_player_id; ids_count++; } } } if ( !ids_count ) { delete [] ids; return; } INIT_PACKET( PCKT_DUP_LOGIN_RQST ); PXO_ADD_INT( Multi_tracker_id ); Assert( MAX_PLAYERS <= 255 ); ubyte tvar = (ubyte)ids_count; PXO_ADD_DATA( tvar ); for (idx = 0; idx < ids_count; idx++) { PXO_ADD_INT( ids[idx] ); } DONE_PACKET(); FS2NetD_SendData(buffer, buffer_size); delete [] ids; }
// lookup the "next" player in the netplayer list, return null if not found net_player *multi_pinfo_get_next_player(net_player *np) { int start_index; int idx; // get the starting index to look from start_index = NET_PLAYER_INDEX(np); if(start_index < (MAX_PLAYERS - 1)){ // look forwards for(idx=start_index+1; idx<MAX_PLAYERS; idx++){ if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){ return &Net_players[idx]; } } } return NULL; }
// lookup the "previous" player in the netplayer list, return null if not found net_player *multi_pinfo_get_prev_player(net_player *np) { int start_index; int idx; // get the starting index to look from start_index = NET_PLAYER_INDEX(np); if(start_index > 0){ // look backwards for(idx=start_index-1; idx>=0; idx--){ if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){ return &Net_players[idx]; } } } return NULL; }
// call once per level just before entering the mission void multi_df_level_pre_enter() { int idx; // if we're not in dogfight mode, do nothing if(!(Netgame.type_flags & NG_TYPE_DOGFIGHT)){ return; } // go through all player ships and make them hostile for(idx=0; idx<MAX_PLAYERS; idx++){ if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_OBSERVER(Net_players[idx]) && (Net_players[idx].m_player != NULL) && (Net_players[idx].m_player->objnum >= 0) && (Objects[Net_players[idx].m_player->objnum].type == OBJ_SHIP)){ Ships[Objects[Net_players[idx].m_player->objnum].instance].team = Iff_traitor; } } // }
// setup kill matrix data void multi_df_setup_kill_matrix() { int idx, s_idx; multi_df_score *s; Multi_df_score_count = 0; // add players as necessary for(idx=0; idx<MAX_PLAYERS; idx++){ if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) && (Net_players[idx].m_player != NULL)){ // stuff data for this guy s = &Multi_df_score[Multi_df_score_count++]; ml_printf("Dogfight debrief stats for %s", Net_players[idx].m_player->callsign); for(s_idx=0; s_idx<MAX_PLAYERS; s_idx++){ ml_printf("%d", Net_players[idx].m_player->stats.m_dogfight_kills[s_idx]); } s->stats = Net_players[idx].m_player->stats; strcpy_s(s->callsign, Net_players[idx].m_player->callsign); s->np_index = idx; } } }
// int Test_color = 0; void chatbox_add_line(const char *msg, int pid, int add_id) { int backup; int n_lines,idx; int n_chars[3]; const char *p_str[3]; // for the initial line (unindented) char msg_extra[CHATBOX_STRING_LEN]; if(!Chatbox_created){ return; } // maybe stick on who sent the message if(add_id){ if(MULTI_STANDALONE(Net_players[pid])){ sprintf(msg_extra, NOX("%s %s"), NOX("<SERVER>"), msg ); } else { sprintf(msg_extra, NOX("%s: %s"), Net_players[pid].m_player->short_callsign, msg ); } } else { strcpy_s(msg_extra,msg); } Assert(strlen(msg_extra) < (CHATBOX_STRING_LEN - 2)); // split the text up into as many lines as necessary n_lines = split_str(msg_extra, Chatbox_disp_w, n_chars, p_str, 3); Assert(n_lines != -1); // setup the first line -- be sure to clear out the line memset( Brief_chat_lines[Brief_current_add_line], 0, CHATBOX_STRING_LEN ); // add the player id # Brief_chat_lines[Brief_current_add_line][0] = (char)(pid % 16); // Brief_chat_lines[Brief_current_add_line][0] = (char)Test_color; // Test_color = (Test_color == MAX_PLAYERS - 1) ? 0 : Test_color++; // set the indent to 0 Brief_chat_indents[Brief_current_add_line] = 0; // copy in the chars strncpy(&Brief_chat_lines[Brief_current_add_line][1],p_str[0],CHATBOX_STRING_LEN - 1); if(n_chars[0] >= CHATBOX_STRING_LEN){ Brief_chat_lines[Brief_current_add_line][CHATBOX_STRING_LEN - 1] = '\0'; } else { Brief_chat_lines[Brief_current_add_line][n_chars[0] + 1] = '\0'; } // increment the total line count if we haven't reached the max already if(Num_brief_chat_lines<MAX_BRIEF_CHAT_LINES){ Num_brief_chat_lines++; } // get the index of the next string to add text to Brief_current_add_line = Brief_chat_next_index[Brief_current_add_line]; // if we have more than 1 line, re-split everything so that the rest are indented if(n_lines > 1){ // split up the string after the first break-marker n_lines = split_str(msg_extra + n_chars[0],Chatbox_disp_w - CHAT_LINE_INDENT,n_chars,p_str,3); Assert(n_lines != -1); // setup these remaining lines for(idx=0;idx<n_lines;idx++){ // add the player id# Brief_chat_lines[Brief_current_add_line][0] = (char)(pid % 16); // add the proper indent Brief_chat_indents[Brief_current_add_line] = CHAT_LINE_INDENT; // copy in the line text itself strncpy(&Brief_chat_lines[Brief_current_add_line][1],p_str[idx],CHATBOX_STRING_LEN-1); if(n_chars[idx] >= CHATBOX_STRING_LEN){ Brief_chat_lines[Brief_current_add_line][CHATBOX_STRING_LEN - 1] = '\0'; } else { Brief_chat_lines[Brief_current_add_line][n_chars[idx] + 1] = '\0'; } // increment the total line count if we haven't reached the max already if(Num_brief_chat_lines<MAX_BRIEF_CHAT_LINES){ Num_brief_chat_lines++; } // get the index of the next line to add text to Brief_current_add_line = Brief_chat_next_index[Brief_current_add_line]; } } // COMMAND LINE OPTION if(Cmdline_multi_stream_chat_to_file && Multi_chat_stream!=NULL && msg[0] != '\0'){ // stream to the file if we're supposed to cfwrite_string(msg,Multi_chat_stream); cfwrite_char('\n',Multi_chat_stream); } // if this line of text is from the player himself, automatically go to the bottom of // the chat list if(pid == MY_NET_PLAYER_NUM){ if(Num_brief_chat_lines > Chatbox_max_lines){ Brief_start_display_index = Brief_current_add_line; for(backup = 1;backup <= Chatbox_max_lines;backup++){ Brief_start_display_index = Brief_chat_prev_index[Brief_start_display_index]; } } } // if we have enough lines of text to require scrolling, scroll down by one. else { chatbox_scroll_down(); } }
// create complete priority sorted escort list for all active ships // escorts - array of escort info // num_escorts - number of escorts requests in field of active ships // This will be culled to MAX_ESCORTS, selecting the top set from escorts void hud_create_complete_escort_list(escort_info *escorts, int *num_escorts) { ship_obj *so; object *objp; // start with none on list *num_escorts = 0; int idx; // multiplayer dogfight if(MULTI_DOGFIGHT){ for(idx=0; idx<MAX_PLAYERS; idx++){ // break out of the loop when we have reached our max if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) { mprintf(("exceeded max ships in big escort list\n")); break; } // is this a valid player if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_OBSERVER(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){ // add the ship escorts[*num_escorts].objnum = -1; escorts[*num_escorts].obj_signature = -1; escorts[*num_escorts].priority = -1; escorts[*num_escorts].np_id = Net_players[idx].player_id; escorts[*num_escorts].escort_hit_timer = 0; escorts[*num_escorts].escort_hit_next_flash = 0; escorts[*num_escorts].escort_show_bright = false; (*num_escorts)++; } } } // all others else { for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) { Assert( so->objnum >= 0 && so->objnum < MAX_OBJECTS); if((so->objnum < 0) || (so->objnum >= MAX_OBJECTS)){ continue; } objp = &Objects[so->objnum]; Assert( objp->type == OBJ_SHIP ); if(objp->type != OBJ_SHIP){ continue; } // break out of the loop when we have reached our max if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) { mprintf(("exceeded max ships in big escort list\n")); break; } // only process ships that might be on the list if ( !(Ships[objp->instance].flags[Ship::Ship_Flags::Escort]) ){ continue; } // only process ships that can be seen by sensors if ( (Ships[objp->instance].flags[Ship::Ship_Flags::Hidden_from_sensors]) ){ continue; } // don't process most stealth ships if ( (Ships[objp->instance].flags[Ship::Ship_Flags::Stealth]) ) { if ( Ships[objp->instance].team == Player_ship->team ) { // friendly stealths are only not seen when explicitly specified if ( Ships[objp->instance].flags[Ship::Ship_Flags::Friendly_stealth_invis] ) { continue; } } // non-friendly stealths are never seen else { continue; } } // don't process objects that should be dead if ( objp->flags[Object::Object_Flags::Should_be_dead] ) { continue; } // add the ship escorts[*num_escorts].objnum = so->objnum; escorts[*num_escorts].obj_signature = objp->signature; escorts[*num_escorts].priority = Ships[objp->instance].escort_priority; escorts[*num_escorts].np_id = -1; escorts[*num_escorts].escort_hit_timer = 0; escorts[*num_escorts].escort_hit_next_flash = 0; escorts[*num_escorts].escort_show_bright = false; (*num_escorts)++; } } }
// create complete priority sorted escort list for all active ships // escorts - array of escort info // num_escorts - number of escorts requests in field of active ships // This will be culled to MAX_ESCORTS, selecting the top set from escorts void hud_create_complete_escort_list(escort_info *escorts, int *num_escorts) { ship_obj *so; object *objp; // start with none on list *num_escorts = 0; int idx; // multiplayer dogfight if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){ for(idx=0; idx<MAX_PLAYERS; idx++){ // break out of the loop when we have reached our max if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) { mprintf(("exceeded max ships in big escort list")); break; } // is this a valid player if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_OBSERVER(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){ // add the ship escorts[*num_escorts].objnum = -1; escorts[*num_escorts].obj_signature = -1; escorts[*num_escorts].priority = -1; escorts[*num_escorts].np_id = Net_players[idx].player_id; (*num_escorts)++; } } } // all others else { for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) { Assert( so->objnum >= 0 && so->objnum < MAX_OBJECTS); if((so->objnum < 0) || (so->objnum >= MAX_OBJECTS)){ continue; } objp = &Objects[so->objnum]; Assert( objp->type == OBJ_SHIP ); if(objp->type != OBJ_SHIP){ continue; } // break out of the loop when we have reached our max if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) { mprintf(("exceeded max ships in big escort list")); break; } // only process ships that might be on the list if ( !(Ships[objp->instance].flags & SF_ESCORT) ){ continue; } // only process ships that can be seen by sensors if ( (Ships[objp->instance].flags & SF_HIDDEN_FROM_SENSORS) ){ continue; } // don't process most stealth ships if ( (Ships[objp->instance].flags2 & SF2_STEALTH) ) { if ( Ships[objp->instance].team == Player_ship->team ) { // friendly stealths are only not seen when explicitly specified if ( Ships[objp->instance].flags2 & SF2_FRIENDLY_STEALTH_INVIS ) { continue; } } // non-friendly stealths are never seen else { continue; } } // don't process ships that are dying, or objects that should be dead if ( (Ships[objp->instance].flags & (SF_DYING|SF_DEPARTING)) || (objp->flags & OF_SHOULD_BE_DEAD) ){ continue; } // add the ship escorts[*num_escorts].objnum = so->objnum; escorts[*num_escorts].obj_signature = objp->signature; escorts[*num_escorts].priority = Ships[objp->instance].escort_priority; escorts[*num_escorts].np_id = -1; (*num_escorts)++; } } }