entity *collision_test_weapon_with_any_target (entity *weapon, vec3d *weapon_old_position, vec3d *weapon_new_position) { entity *launcher, *collision_entity; vec3d weapon_intercept_point, face_normal; ASSERT (weapon); ASSERT (weapon_old_position); ASSERT (weapon_new_position); ASSERT (get_comms_model () == COMMS_MODEL_SERVER); launcher = get_local_entity_parent (weapon, LIST_TYPE_LAUNCHED_WEAPON); collision_entity = get_line_of_sight_collision_entity (launcher, NULL, weapon_old_position, weapon_new_position, &weapon_intercept_point, &face_normal); if (collision_entity) { *weapon_new_position = weapon_intercept_point; } return (collision_entity); }
int check_position_line_of_sight (entity *source, entity *target, vec3d *source_position, vec3d *target_position, mobile_los_check_criteria criteria) { entity *collision_en; vec3d increment, collision_point, normal, #if LINE_DEBUG_MODULE old_position, #endif check_position, direction; float target_range, collision_distance, number_of_terrain_checks, terrain_elevation; terrain_3d_point_data terrain_info; ASSERT (source); ASSERT (target); ASSERT (source_position); ASSERT (target_position); direction.x = target_position->x - source_position->x; direction.y = target_position->y - source_position->y; direction.z = target_position->z - source_position->z; target_range = sqrt ((direction.x * direction.x) + (direction.z * direction.z)); normalise_3d_vector (&direction); //////////////////////////////////////////////////////////////// // COARSE line of sight check with terrain //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_COURSE_TERRAIN) { number_of_terrain_checks = target_range / LOS_COARSE_CHECK_DISTANCE; increment.x = direction.x * LOS_COARSE_CHECK_DISTANCE; increment.y = direction.y * LOS_COARSE_CHECK_DISTANCE; increment.z = direction.z * LOS_COARSE_CHECK_DISTANCE; check_position = *source_position; memset (&terrain_info, 0, sizeof (terrain_3d_point_data)); while (number_of_terrain_checks > 1.0) { #if LINE_DEBUG_MODULE old_position = check_position; #endif check_position.x += increment.x; check_position.y += increment.y; check_position.z += increment.z; get_3d_terrain_point_data (check_position.x, check_position.z, &terrain_info); terrain_elevation = get_3d_terrain_point_data_elevation (&terrain_info); if (terrain_elevation > check_position.y) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed COURSE terrain LOS", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME)); #endif return FALSE; } #if LINE_DEBUG_MODULE create_debug_3d_line (&old_position, &check_position, sys_col_yellow, 10.0); #endif number_of_terrain_checks --; } } //////////////////////////////////////////////////////////////// // SOURCE END FINE line of sight check with terrain //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_SOURCE_END_TERRAIN) { number_of_terrain_checks = target_range / LOS_FINE_CHECK_DISTANCE_SOURCE_END; number_of_terrain_checks = min (number_of_terrain_checks, LOS_NUMBER_OF_FINE_CHECKS_SOURCE_END); increment.x = direction.x * LOS_FINE_CHECK_DISTANCE_SOURCE_END; increment.y = direction.y * LOS_FINE_CHECK_DISTANCE_SOURCE_END; increment.z = direction.z * LOS_FINE_CHECK_DISTANCE_SOURCE_END; check_position = *source_position; while (number_of_terrain_checks > 1.0) { #if LINE_DEBUG_MODULE old_position = check_position; #endif check_position.x += increment.x; check_position.y += increment.y; check_position.z += increment.z; get_3d_terrain_point_data (check_position.x, check_position.z, &terrain_info); terrain_elevation = get_3d_terrain_point_data_elevation (&terrain_info); if (terrain_elevation > check_position.y) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed FINE terrain LOS (source end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME)); #endif return FALSE; } #if LINE_DEBUG_MODULE create_debug_3d_line (&old_position, &check_position, sys_col_yellow, 10.0); #endif number_of_terrain_checks --; } } //////////////////////////////////////////////////////////////// // TARGET END FINE line of sight check with terrain //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_TARGET_END_TERRAIN) { number_of_terrain_checks = target_range / LOS_FINE_CHECK_DISTANCE_TARGET_END; number_of_terrain_checks = min (number_of_terrain_checks, LOS_NUMBER_OF_FINE_CHECKS_TARGET_END); increment.x = direction.x * LOS_FINE_CHECK_DISTANCE_TARGET_END; increment.y = direction.y * LOS_FINE_CHECK_DISTANCE_TARGET_END; increment.z = direction.z * LOS_FINE_CHECK_DISTANCE_TARGET_END; check_position = *target_position; while (number_of_terrain_checks > 1.0) { #if LINE_DEBUG_MODULE old_position = check_position; #endif check_position.x -= increment.x; check_position.y -= increment.y; check_position.z -= increment.z; get_3d_terrain_point_data (check_position.x, check_position.z, &terrain_info); terrain_elevation = get_3d_terrain_point_data_elevation (&terrain_info); if (terrain_elevation > check_position.y) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed FINE terrain LOS (target end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME)); #endif return FALSE; } #if LINE_DEBUG_MODULE create_debug_3d_line (&old_position, &check_position, sys_col_yellow, 10.0); #endif number_of_terrain_checks --; } } //////////////////////////////////////////////////////////////// // SOURCE END line of sight check with objects //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_SOURCE_END_OBJECTS) { check_position.x = source_position->x + (direction.x * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.y = source_position->y + (direction.y * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.z = source_position->z + (direction.z * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); collision_en = get_line_of_sight_collision_entity ( source, target, source_position, &check_position, &collision_point, &normal ); if (collision_en) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed OBJECT LOS with %s (source end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_type_name (collision_en)); #endif return FALSE; } } //////////////////////////////////////////////////////////////// // TARGET END line of sight check with objects //////////////////////////////////////////////////////////////// if (criteria & MOBILE_LOS_CHECK_TARGET_END_OBJECTS) { check_position.x = target_position->x - (direction.x * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.y = target_position->y - (direction.y * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); check_position.z = target_position->z - (direction.z * LOS_OBJECT_CHECK_DISTANCE_TARGET_END); collision_en = get_line_of_sight_collision_entity ( source, target, target_position, &check_position, &collision_point, &normal ); if (collision_en) { collision_distance = get_sqr_3d_range (&collision_point, target_position); if (collision_distance > (LOS_OBJECT_EXCLUDE_DISTANCE_TARGET_END * LOS_OBJECT_EXCLUDE_DISTANCE_TARGET_END)) { #if TEXT_DEBUG_MODULE debug_log ("MB_TGT: (%s -> %s) failed OBJECT LOS with %s (target end)", get_local_entity_string (source, STRING_TYPE_FULL_NAME), get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_type_name (collision_en)); #endif return FALSE; } } } return TRUE; }