// update team visibility void team_visibility_update() { int team_count[MAX_IFFS]; int team_ships[MAX_IFFS][MAX_SHIPS]; ship_obj *moveup; ship *shipp; // zero out stuff for each team memset(team_count, 0, MAX_IFFS * sizeof(int)); memset(Ship_visibility_by_team, 0, MAX_IFFS * MAX_SHIPS * sizeof(ubyte)); // Go through list of ships and mark those visible for their own team for (moveup = GET_FIRST(&Ship_obj_list); moveup != END_OF_LIST(&Ship_obj_list); moveup = GET_NEXT(moveup)) { // make sure its a valid ship if ((Objects[moveup->objnum].type != OBJ_SHIP) || (Objects[moveup->objnum].instance < 0)) continue; // get a handle to the ship int ship_num = Objects[moveup->objnum].instance; shipp = &Ships[ship_num]; // ignore dying, departing, or arriving ships if (shipp->is_dying_or_departing() || shipp->is_arriving()) continue; // check if ship is flagged as invisible if (shipp->flags[Ship::Ship_Flags::Hidden_from_sensors]) continue; // check if ship is stealthed and friendly-invisible if ((shipp->flags[Ship::Ship_Flags::Stealth] && shipp->flags[Ship::Ship_Flags::Friendly_stealth_invis])) continue; Ship_visibility_by_team[shipp->team][ship_num] = 1; team_ships[shipp->team][team_count[shipp->team]] = ship_num; team_count[shipp->team]++; } int idx, en_idx, cur_count, en_count; int *cur_team_ships, *en_team_ships; // Do for all teams that cooperate with visibility for (int cur_team = 0; cur_team < MAX_IFFS; cur_team++) { // set up current team cur_count = team_count[cur_team]; cur_team_ships = team_ships[cur_team]; // short circuit if team has no presence if (cur_count == 0) continue; // Goober5000 10/06/2005 changed from break; probably a bug // check against all enemy teams for (int en_team = 0; en_team < MAX_IFFS; en_team++) { // NOTE: we no longer skip our own team because we must adjust visibility for friendly-stealth-invisible ships // if (en_team == cur_team) // continue; // set up enemy team en_count = team_count[en_team]; en_team_ships = team_ships[en_team]; // check if current team can see enemy team's ships for (en_idx = 0; en_idx < en_count; en_idx++) { // for each ship on other team for (idx = 0; idx < cur_count; idx++) { // ignore nav buoys and cargo containers if (Ship_info[Ships[cur_team_ships[idx]].ship_info_index].flags[Ship::Info_Flags::Cargo] || Ship_info[Ships[cur_team_ships[idx]].ship_info_index].flags[Ship::Info_Flags::Navbuoy]) { continue; } // check against each ship on my team (and AWACS only once) if (awacs_get_level(&Objects[Ships[en_team_ships[en_idx]].objnum], &Ships[cur_team_ships[idx]], (idx == 0)) > 1.0f) { Ship_visibility_by_team[cur_team][en_team_ships[en_idx]] = 1; break; } } } } } }
void radar_plot_object( object *objp ) { vector pos, tempv; float dist, rscale, zdist, max_radar_dist; int xpos, ypos, color=0; vector *world_pos = &objp->pos; float awacs_level; // don't process anything here. Somehow, a jumpnode object caused this function // to get entered on server side. if( Game_mode & GM_STANDALONE_SERVER ){ return; } // multiplayer clients ingame joining should skip this function if ( MULTIPLAYER_CLIENT && (Net_player->flags & NETINFO_FLAG_INGAME_JOIN) ){ return; } // get team-wide awacs level for the object if not ship int ship_is_visible = 0; if (objp->type == OBJ_SHIP) { if (Player_ship != NULL) { if (ship_is_visible_by_team(objp->instance, Player_ship->team)) { ship_is_visible = 1; } } } // only check awacs level if ship is not visible by team awacs_level = 1.5f; if (Player_ship != NULL && !ship_is_visible) { awacs_level = awacs_get_level(objp, Player_ship); } // if the awacs level is unviewable - bail if(awacs_level < 0.0f && !See_all){ return; } // Apply object type filters switch ( objp->type ) { case OBJ_SHIP: // Place to cull ships, such as NavBuoys break; case OBJ_JUMP_NODE: // filter jump nodes here if required break; case OBJ_WEAPON: { // if not a bomb, return if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_BOMB) ) { return; } // if bomb is on same team as player, return if ( (obj_team(objp) == Player_ship->team) && (Player_ship->team != TEAM_TRAITOR) ) { return; } break; } default: return; // if any other kind of object, don't want to show on radar break; } // end switch // JAS -- new way of getting the rotated point that doesn't require this to be // in a g3_start_frame/end_frame block. vm_vec_sub(&tempv,world_pos,&Player_obj->pos); vm_vec_rotate( &pos, &tempv, &Player_obj->orient ); // Apply range filter dist = vm_vec_dist(world_pos, &Player_obj->pos); max_radar_dist = Radar_ranges[HUD_config.rp_dist]; if ( dist > max_radar_dist ){ return; } if ( dist < pos.xyz.z ) { rscale = 0.0f; } else { rscale = (float) acos( pos.xyz.z/dist ) / 3.14159f; //2.0f; } zdist = fl_sqrt( (pos.xyz.x*pos.xyz.x)+(pos.xyz.y*pos.xyz.y) ); float new_x_dist, clipped_x_dist; float new_y_dist, clipped_y_dist; if (zdist < 0.01f ) { new_x_dist = 0.0f; new_y_dist = 0.0f; } else { new_x_dist = (pos.xyz.x/zdist) * rscale * radx; new_y_dist = (pos.xyz.y/zdist) * rscale * rady; // force new_x_dist and new_y_dist to be inside the radar float hypotenuse; float max_radius; hypotenuse = (float)_hypot(new_x_dist, new_y_dist); max_radius = i2fl(Radar_radius[gr_screen.res][0] - 5); if (hypotenuse >= (max_radius) ) { clipped_x_dist = max_radius * (new_x_dist / hypotenuse); clipped_y_dist = max_radius * (new_y_dist / hypotenuse); new_x_dist = clipped_x_dist; new_y_dist = clipped_y_dist; } } xpos = fl2i( Radar_center[gr_screen.res][0] + new_x_dist ); ypos = fl2i( Radar_center[gr_screen.res][1] - new_y_dist ); color = radar_blip_color(objp); // Determine the distance at which we will dim the radar blip if ( timestamp_elapsed(Radar_calc_dim_dist_timer) ) { Radar_calc_dim_dist_timer=timestamp(1000); Radar_dim_range = player_farthest_weapon_range(); if ( Radar_dim_range <= 0 ) { Radar_dim_range=1500.0f; } } blip *b; int blip_dim=0; if ( dist > Radar_dim_range ) { blip_dim=1; } if ( N_blips >= MAX_BLIPS ) { // out of blips, don't plot Int3(); return; } b = &Blips[N_blips]; b->flags=0; // flag the blip as a current target if it is if (OBJ_INDEX(objp) == Player_ai->target_objnum) { b->flags |= BLIP_CURRENT_TARGET; blip_dim = 0; } if ( blip_dim ) { list_append( &Blip_dim_list[color], b ); } else { list_append( &Blip_bright_list[color], b ); } b->x = xpos; b->y = ypos; // see if blip should be drawn distorted if (objp->type == OBJ_SHIP) { // ships specifically hidden from sensors if ( Ships[objp->instance].flags & SF_HIDDEN_FROM_SENSORS ) { b->flags |= BLIP_DRAW_DISTORTED; } // determine if its AWACS distorted if ( awacs_level < 1.0f ){ b->flags |= BLIP_DRAW_DISTORTED; } } N_blips++; }
void radar_plot_object( object *objp ) { vec3d pos, tempv; float awacs_level, dist, max_radar_dist; vec3d world_pos = objp->pos; SCP_list<CJumpNode>::iterator jnp; // don't process anything here. Somehow, a jumpnode object caused this function // to get entered on server side. if( Game_mode & GM_STANDALONE_SERVER ){ return; } // multiplayer clients ingame joining should skip this function if ( MULTIPLAYER_CLIENT && (Net_player->flags & NETINFO_FLAG_INGAME_JOIN) ){ return; } // get team-wide awacs level for the object if not ship int ship_is_visible = 0; if (objp->type == OBJ_SHIP) { if (Player_ship != NULL) { if (ship_is_visible_by_team(objp, Player_ship)) { ship_is_visible = 1; } } } // only check awacs level if ship is not visible by team awacs_level = 1.5f; if (Player_ship != NULL && !ship_is_visible) { awacs_level = awacs_get_level(objp, Player_ship); } // if the awacs level is unviewable - bail if(awacs_level < 0.0f && !See_all){ return; } // Apply object type filters switch (objp->type) { case OBJ_SHIP: // Place to cull ships, such as NavBuoys break; case OBJ_JUMP_NODE: { for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { if(jnp->GetSCPObject() == objp) break; } // don't plot hidden jump nodes if ( jnp->IsHidden() ) return; // filter jump nodes here if required break; } case OBJ_WEAPON: { // if not a bomb, return if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_SHOWN_ON_RADAR) ) if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_BOMB) ) return; // if explicitly hidden, return if (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_DONT_SHOW_ON_RADAR) return; // if we don't attack the bomb, return if ( (!(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_SHOW_FRIENDLY)) && (!iff_x_attacks_y(Player_ship->team, obj_team(objp)))) return; // if a local ssm is in subspace, return if (Weapons[objp->instance].lssm_stage == 3) return; // if corkscrew missile use last frame pos for pos if ( (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_CORKSCREW) ) world_pos = objp->last_pos; break; } // if any other kind of object, don't show it on radar default: return; } // Retrieve the eye orientation so we can position the blips relative to it matrix eye_orient; if (Player_obj->type == OBJ_SHIP) ship_get_eye(&tempv, &eye_orient, Player_obj, false , false); else eye_orient = Player_obj->orient; // JAS -- new way of getting the rotated point that doesn't require this to be // in a g3_start_frame/end_frame block. vm_vec_sub(&tempv, &world_pos, &Player_obj->pos); vm_vec_rotate(&pos, &tempv, &eye_orient); // Apply range filter dist = vm_vec_dist(&world_pos, &Player_obj->pos); max_radar_dist = Radar_ranges[HUD_config.rp_dist]; if (dist > max_radar_dist) { return; } // determine the range within which the radar blip is bright if (timestamp_elapsed(Radar_calc_bright_dist_timer)) { Radar_calc_bright_dist_timer = timestamp(1000); Radar_bright_range = player_farthest_weapon_range(); if (Radar_bright_range <= 0) Radar_bright_range = 1500.0f; } blip *b; int blip_bright = 0; int blip_type = 0; if (N_blips >= MAX_BLIPS) { return; } b = &Blips[N_blips]; b->flags = 0; // bright if within range blip_bright = (dist <= Radar_bright_range); // flag the blip as a current target if it is if (OBJ_INDEX(objp) == Player_ai->target_objnum) { b->flags |= BLIP_CURRENT_TARGET; blip_bright = 1; } radar_stuff_blip_info(objp, blip_bright, &b->blip_color, &blip_type); if (blip_bright) list_append(&Blip_bright_list[blip_type], b); else list_append(&Blip_dim_list[blip_type], b); b->position = pos; b->dist = dist; b->objp = objp; b->radar_image_2d = -1; b->radar_color_image_2d = -1; b->radar_image_size = -1; b->radar_projection_size = 1.0f; // see if blip should be drawn distorted // also determine if alternate image was defined for this ship if (objp->type == OBJ_SHIP) { // ships specifically hidden from sensors if (Ships[objp->instance].flags & SF_HIDDEN_FROM_SENSORS) b->flags |= BLIP_DRAW_DISTORTED; // determine if its AWACS distorted if (awacs_level < 1.0f) b->flags |= BLIP_DRAW_DISTORTED; ship_info *Iff_ship_info = &Ship_info[Ships[objp->instance].ship_info_index]; if (Iff_ship_info->radar_image_2d_idx >= 0 || Iff_ship_info->radar_color_image_2d_idx >= 0) { b->radar_image_2d = Iff_ship_info->radar_image_2d_idx; b->radar_color_image_2d = Iff_ship_info->radar_color_image_2d_idx; b->radar_image_size = Iff_ship_info->radar_image_size; b->radar_projection_size = Iff_ship_info->radar_projection_size_mult; } } // don't distort the sensor blips if the player has primitive sensors and the nebula effect // is not active if (Player_ship->flags2 & SF2_PRIMITIVE_SENSORS) { if (!(The_mission.flags & MISSION_FLAG_FULLNEB)) b->flags &= ~BLIP_DRAW_DISTORTED; } N_blips++; }
/** * @brief Return if the specified object is visible on the radar * * @param objp The object which should be checked * @return A RadarVisibility enum specifying the visibility of the specified object */ RadarVisibility radar_is_visible( object *objp ) { Assert( objp != NULL ); if (objp->flags & OF_SHOULD_BE_DEAD) { return NOT_VISIBLE; } vec3d pos, tempv; float awacs_level, dist, max_radar_dist; vec3d world_pos = objp->pos; SCP_list<CJumpNode>::iterator jnp; // get team-wide awacs level for the object if not ship int ship_is_visible = 0; if (objp->type == OBJ_SHIP) { if (Player_ship != NULL) { if (ship_is_visible_by_team(objp, Player_ship)) { ship_is_visible = 1; } } } // only check awacs level if ship is not visible by team awacs_level = 1.5f; if (Player_ship != NULL && !ship_is_visible) { awacs_level = awacs_get_level(objp, Player_ship); } // if the awacs level is unviewable - bail if(awacs_level < 0.0f && !See_all){ return NOT_VISIBLE; } // Apply object type filters switch (objp->type) { case OBJ_SHIP: if (Ships[objp->instance].flags & SIF_STEALTH) return NOT_VISIBLE; // Ships that are warp in in are not visible on the radar if (Ships[objp->instance].flags & SF_ARRIVING_STAGE_1) return NOT_VISIBLE; break; case OBJ_JUMP_NODE: { for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) { if(jnp->GetSCPObject() == objp) break; } // don't plot hidden jump nodes if ( jnp->IsHidden() ) return NOT_VISIBLE; // filter jump nodes here if required break; } case OBJ_WEAPON: { // if not a bomb, return if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_SHOWN_ON_RADAR) ) if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_BOMB) ) return NOT_VISIBLE; // if explicitly hidden, return if (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_DONT_SHOW_ON_RADAR) return NOT_VISIBLE; // if we don't attack the bomb, return if ( (!(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags2 & WIF2_SHOW_FRIENDLY)) && (!iff_x_attacks_y(Player_ship->team, obj_team(objp)))) return NOT_VISIBLE; // if a local ssm is in subspace, return if (Weapons[objp->instance].lssm_stage == 3) return NOT_VISIBLE; break; } // if any other kind of object, don't show it on radar default: return NOT_VISIBLE; } vm_vec_sub(&tempv, &world_pos, &Player_obj->pos); vm_vec_rotate(&pos, &tempv, &Player_obj->orient); // Apply range filter dist = vm_vec_dist(&world_pos, &Player_obj->pos); max_radar_dist = Radar_ranges[HUD_config.rp_dist]; if (dist > max_radar_dist) { return NOT_VISIBLE; } if (objp->type == OBJ_SHIP) { // ships specifically hidden from sensors if (Ships[objp->instance].flags & SF_HIDDEN_FROM_SENSORS) return DISTORTED; // determine if its AWACS distorted if (awacs_level < 1.0f) return DISTORTED; } return VISIBLE; }
void radar_plot_object_std( object *objp ) { vec3d pos, tempv; float dist, rscale, zdist, max_radar_dist; int xpos, ypos; vec3d *world_pos = &objp->pos; float awacs_level; // don't process anything here. Somehow, a jumpnode object caused this function // to get entered on server side. if( Game_mode & GM_STANDALONE_SERVER ){ return; } // multiplayer clients ingame joining should skip this function if ( MULTIPLAYER_CLIENT && (Net_player->flags & NETINFO_FLAG_INGAME_JOIN) ){ return; } // get team-wide awacs level for the object if not ship int ship_is_visible = 0; if (objp->type == OBJ_SHIP) { if (Player_ship != NULL) { if (ship_is_visible_by_team(objp, Player_ship)) { ship_is_visible = 1; } } } // only check awacs level if ship is not visible by team awacs_level = 1.5f; if (Player_ship != NULL && !ship_is_visible) { awacs_level = awacs_get_level(objp, Player_ship); } // if the awacs level is unviewable - bail if(awacs_level < 0.0f && !See_all){ return; } // Apply object type filters switch (objp->type) { case OBJ_SHIP: // Place to cull ships, such as NavBuoys break; case OBJ_JUMP_NODE: { // don't plot hidden jump nodes if ( objp->jnp->is_hidden() ) return; // filter jump nodes here if required break; } case OBJ_WEAPON: { // if not a bomb, return if ( !(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_BOMB) ) return; // if we don't attack the bomb, return if ( !iff_x_attacks_y(Player_ship->team, obj_team(objp)) ) return; // if a local ssm is in subspace, return if (Weapons[objp->instance].lssm_stage == 3) return; break; } // if any other kind of object, don't show it on radar default: return; } // JAS -- new way of getting the rotated point that doesn't require this to be // in a g3_start_frame/end_frame block. vm_vec_sub(&tempv, world_pos, &Player_obj->pos); vm_vec_rotate(&pos, &tempv, &Player_obj->orient); // Apply range filter dist = vm_vec_dist(world_pos, &Player_obj->pos); max_radar_dist = Radar_ranges[HUD_config.rp_dist]; if (dist > max_radar_dist) { return; } if (dist < pos.xyz.z) { rscale = 0.0f; } else { rscale = (float) acos(pos.xyz.z / dist) / 3.14159f; //2.0f; } zdist = fl_sqrt((pos.xyz.x * pos.xyz.x) + (pos.xyz.y * pos.xyz.y)); float new_x_dist, clipped_x_dist; float new_y_dist, clipped_y_dist; if (zdist < 0.01f) { new_x_dist = 0.0f; new_y_dist = 0.0f; } else { new_x_dist = (pos.xyz.x / zdist) * rscale * radx; new_y_dist = (pos.xyz.y / zdist) * rscale * rady; // force new_x_dist and new_y_dist to be inside the radar float hypotenuse; float max_radius; hypotenuse = (float) _hypot(new_x_dist, new_y_dist); max_radius = i2fl(Current_radar_global->Radar_radius[gr_screen.res][0] - 5); if (hypotenuse >= max_radius) { clipped_x_dist = max_radius * (new_x_dist / hypotenuse); clipped_y_dist = max_radius * (new_y_dist / hypotenuse); new_x_dist = clipped_x_dist; new_y_dist = clipped_y_dist; } } xpos = fl2i(Current_radar_global->Radar_center[gr_screen.res][0] + new_x_dist); ypos = fl2i(Current_radar_global->Radar_center[gr_screen.res][1] - new_y_dist); // determine the range within which the radar blip is bright if (timestamp_elapsed(Radar_calc_bright_dist_timer)) { Radar_calc_bright_dist_timer = timestamp(1000); Radar_bright_range = player_farthest_weapon_range(); if (Radar_bright_range <= 0) Radar_bright_range = 1500.0f; } blip *b; int blip_bright = 0; int blip_type = 0; if (N_blips >= MAX_BLIPS) { // out of blips, don't plot //Gahhh, this is bloody annoying -WMC //Int3(); return; } b = &Blips[N_blips]; b->flags = 0; // bright if within range blip_bright = (dist <= Radar_bright_range); // flag the blip as a current target if it is if (OBJ_INDEX(objp) == Player_ai->target_objnum) { b->flags |= BLIP_CURRENT_TARGET; blip_bright = 1; } radar_stuff_blip_info_std(objp, blip_bright, &b->blip_color, &blip_type); if (blip_bright) list_append(&Blip_bright_list[blip_type], b); else list_append(&Blip_dim_list[blip_type], b); b->x = xpos; b->y = ypos; // see if blip should be drawn distorted if (objp->type == OBJ_SHIP) { // ships specifically hidden from sensors if (Ships[objp->instance].flags & SF_HIDDEN_FROM_SENSORS) b->flags |= BLIP_DRAW_DISTORTED; // determine if its AWACS distorted if (awacs_level < 1.0f) b->flags |= BLIP_DRAW_DISTORTED; } // don't distort the sensor blips if the player has primitive sensors and the nebula effect // is not active if (Player_ship->flags2 & SF2_PRIMITIVE_SENSORS) { if (!(The_mission.flags & MISSION_FLAG_FULLNEB)) b->flags &= ~BLIP_DRAW_DISTORTED; } N_blips++; }