float get_ka50_missile_flight_time (void) { entity *en, *weapon, *target; vec3d *weapon_position, *target_position; float flight_time, weapon_velocity, target_range; flight_time = 0.0; en = get_gunship_entity (); // // find most recently launched Vikhr with a target (first found on list) // weapon = get_local_entity_first_child (en, LIST_TYPE_LAUNCHED_WEAPON); while (weapon) { if (get_local_entity_int_value (weapon, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_WEAPON_VIKHR) { target = get_local_entity_parent (weapon, LIST_TYPE_TARGET); if (target) { weapon_position = get_local_entity_vec3d_ptr (weapon, VEC3D_TYPE_POSITION); target_position = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION); target_range = get_3d_range (weapon_position, target_position); weapon_velocity = get_local_entity_float_value (weapon, FLOAT_TYPE_VELOCITY); if (weapon_velocity > 0.0) { flight_time = target_range / weapon_velocity; break; } } } weapon = get_local_entity_child_succ (weapon, LIST_TYPE_LAUNCHED_WEAPON); } return (flight_time); }
void update_weapon_lock_type (target_acquisition_systems system) { entity *source, *target; entity_sub_types selected_weapon_type; float target_range, theta, weapon_min_range, weapon_max_range; vec3d *source_position, *target_position, *weapon_vector, *weapon_to_target_vector; //////////////////////////////////////// // // WEAPON_LOCK_NO_ACQUIRE // //////////////////////////////////////// if (system == TARGET_ACQUISITION_SYSTEM_OFF) { weapon_lock_type = WEAPON_LOCK_NO_ACQUIRE; return; } //////////////////////////////////////// // // WEAPON_LOCK_NO_WEAPON // //////////////////////////////////////// source = get_gunship_entity (); selected_weapon_type = get_local_entity_int_value (source, INT_TYPE_SELECTED_WEAPON); if (selected_weapon_type == ENTITY_SUB_TYPE_WEAPON_NO_WEAPON) { weapon_lock_type = WEAPON_LOCK_NO_WEAPON; return; } //////////////////////////////////////// // // WEAPON_LOCK_NO_TARGET // //////////////////////////////////////// target = get_local_entity_parent (source, LIST_TYPE_TARGET); if (!target) { weapon_lock_type = WEAPON_LOCK_NO_TARGET; return; } //////////////////////////////////////// // // WEAPON_LOCK_INVALID_TARGET // //////////////////////////////////////// // // infra-red air-to-air weapons require an airborne target // if (weapon_database[selected_weapon_type].guidance_type == WEAPON_GUIDANCE_TYPE_PASSIVE_INFRA_RED) { if (weapon_database[selected_weapon_type].weapon_class & WEAPON_CLASS_AIR_TO_AIR) { if (!get_local_entity_int_value (target, INT_TYPE_AIRBORNE_AIRCRAFT)) { weapon_lock_type = WEAPON_LOCK_INVALID_TARGET; return; } } } //////////////////////////////////////// // // WEAPON_LOCK_SEEKER_LIMIT // //////////////////////////////////////// // // if guided weapon check target is inside the seeker limit // if (weapon_database[selected_weapon_type].guidance_type != WEAPON_GUIDANCE_TYPE_NONE) { update_entity_weapon_system_weapon_and_target_vectors (source); if (get_local_entity_int_value (source, INT_TYPE_WEAPON_AND_TARGET_VECTORS_VALID)) { weapon_vector = get_local_entity_vec3d_ptr (source, VEC3D_TYPE_WEAPON_VECTOR); weapon_to_target_vector = get_local_entity_vec3d_ptr (source, VEC3D_TYPE_WEAPON_TO_TARGET_VECTOR); theta = get_3d_unit_vector_dot_product (weapon_vector, weapon_to_target_vector); theta = fabs (acos (theta)); if (theta > weapon_database[selected_weapon_type].max_launch_angle_error) { weapon_lock_type = WEAPON_LOCK_SEEKER_LIMIT; return; } } else { // // this should never happen // debug_colour_log (DEBUG_COLOUR_RED, "WARNING! Target and weapon vectors are not valid"); } } //////////////////////////////////////// // // WEAPON_LOCK_NO_LOS // //////////////////////////////////////// // // if air or ground radar then check line of sight // if ((system == TARGET_ACQUISITION_SYSTEM_GROUND_RADAR) || (system == TARGET_ACQUISITION_SYSTEM_AIR_RADAR)) { if (!get_local_entity_int_value (target, INT_TYPE_GUNSHIP_RADAR_LOS_CLEAR)) { weapon_lock_type = WEAPON_LOCK_NO_LOS; return; } } //////////////////////////////////////// // // WEAPON_LOCK_NO_BORESIGHT // //////////////////////////////////////// // // a boresight_weapon will be an unguided weapon so the seeker limit test is not being repeated here // if (weapon_database[selected_weapon_type].boresight_weapon) { update_entity_weapon_system_weapon_and_target_vectors (source); if (get_local_entity_int_value (source, INT_TYPE_WEAPON_AND_TARGET_VECTORS_VALID)) { weapon_vector = get_local_entity_vec3d_ptr (source, VEC3D_TYPE_WEAPON_VECTOR); weapon_to_target_vector = get_local_entity_vec3d_ptr (source, VEC3D_TYPE_WEAPON_TO_TARGET_VECTOR); theta = get_3d_unit_vector_dot_product (weapon_vector, weapon_to_target_vector); theta = fabs (acos (theta)); if (theta > rad (1.0)) { weapon_lock_type = WEAPON_LOCK_NO_BORESIGHT; return; } } else { // // this should never happen // debug_colour_log (DEBUG_COLOUR_RED, "WARNING! Target and weapon vectors are not valid"); } } //////////////////////////////////////// // // WEAPON_LOCK_MIN_RANGE // WEAPON_LOCK_MAX_RANGE // //////////////////////////////////////// source_position = get_local_entity_vec3d_ptr (source, VEC3D_TYPE_POSITION); target_position = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION); target_range = get_3d_range (source_position, target_position); weapon_min_range = weapon_database[selected_weapon_type].min_range; if (weapon_database[selected_weapon_type].hellfire_flight_profile) { if (get_local_entity_int_value (source, INT_TYPE_LOCK_ON_AFTER_LAUNCH)) { weapon_min_range = weapon_database[selected_weapon_type].min_range_loal; } } if (target_range < weapon_min_range) { weapon_lock_type = WEAPON_LOCK_MIN_RANGE; return; } weapon_max_range = weapon_database[selected_weapon_type].max_range; if (weapon_database[selected_weapon_type].hellfire_flight_profile) { if (get_local_entity_int_value (source, INT_TYPE_LOCK_ON_AFTER_LAUNCH)) { weapon_max_range = weapon_database[selected_weapon_type].max_range_loal; } } if (target_range > weapon_max_range) { weapon_lock_type = WEAPON_LOCK_MAX_RANGE; return; } //////////////////////////////////////// // // WEAPON_LOCK_VALID // //////////////////////////////////////// weapon_lock_type = WEAPON_LOCK_VALID; }
float get_viper_missile_flight_time (void) { entity_sub_types weapon_sub_type; entity *en, *weapon, *target; vec3d *weapon_position, *target_position; float flight_time, weapon_velocity, target_range; flight_time = 0.0; en = get_gunship_entity (); // // find most recently launched Hellfire with a target (first found on list) // weapon = get_local_entity_first_child (en, LIST_TYPE_LAUNCHED_WEAPON); while (weapon) { weapon_sub_type = get_local_entity_int_value (weapon, INT_TYPE_ENTITY_SUB_TYPE); if ((weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_AGM114L_LONGBOW_HELLFIRE) || (weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_AGM114K_HELLFIRE_II)) { target = get_local_entity_parent (weapon, LIST_TYPE_TARGET); if (target) { weapon_position = get_local_entity_vec3d_ptr (weapon, VEC3D_TYPE_POSITION); target_position = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION); target_range = get_3d_range (weapon_position, target_position); weapon_velocity = get_local_entity_float_value (weapon, FLOAT_TYPE_VELOCITY); if (weapon_velocity > 0.0) { flight_time = target_range / weapon_velocity; break; } } } weapon = get_local_entity_child_succ (weapon, LIST_TYPE_LAUNCHED_WEAPON); } return (flight_time); }
void draw_debug_guide_entity (entity *en) { waypoint *raw; entity *member, *this_waypoint; vec3d direction, guide_pos, *member_pos, *this_waypoint_position; float length; ASSERT (en); raw = (waypoint *) get_local_entity_data (en); // // get guide position // get_local_entity_vec3d (en, VEC3D_TYPE_GUIDE_POSITION, &guide_pos); // // get waypoint position // this_waypoint_position = NULL; this_waypoint = get_local_entity_parent (en, LIST_TYPE_CURRENT_WAYPOINT); ASSERT (this_waypoint); // // draw guide position // direction.x = 0.0; direction.y = 1.0; direction.z = 0.0; create_vectored_debug_3d_object (&guide_pos, &direction, OBJECT_3D_SPHERICAL_TEST, 0.0, 1.0); if (get_local_entity_int_value (this_waypoint, INT_TYPE_POSITION_TYPE) != POSITION_TYPE_VIRTUAL) { this_waypoint_position = get_local_entity_vec3d_ptr (this_waypoint, VEC3D_TYPE_POSITION); length = get_3d_range (&guide_pos, this_waypoint_position); if (length > 0.0) { create_debug_3d_line (&guide_pos, this_waypoint_position, sys_col_yellow, 0.0); } } // // draw vector to group position // member = get_local_entity_first_child (en, LIST_TYPE_FOLLOWER); while (member) { member_pos = get_local_entity_vec3d_ptr (member, VEC3D_TYPE_POSITION); length = get_3d_range (&guide_pos, member_pos); if (length > 0.0) { create_debug_3d_line (&guide_pos, member_pos, sys_col_light_red, 0.0); } member = get_local_entity_child_succ (member, LIST_TYPE_FOLLOWER); } }
int collision_test_weapon_with_given_target (entity *weapon, entity *target, vec3d *weapon_old_position, vec3d *weapon_new_position) { float range, weapon_velocity, time_to_impact, sqr_velocity; vec3d *target_position, *target_motion_vector, target_old_position, target_new_position, weapon_intercept_point, target_intercept_point; ASSERT (weapon); ASSERT (target); ASSERT (weapon_old_position); ASSERT (weapon_new_position); ASSERT (get_comms_model () == COMMS_MODEL_SERVER); // // approximate time to impact (uses the target position rather than the intercept point) // target_position = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION); range = get_approx_3d_range (target_position, weapon_new_position); weapon_velocity = get_local_entity_float_value (weapon, FLOAT_TYPE_VELOCITY); time_to_impact = range / max (weapon_velocity, 1.0); // // only proceed if close to impact // if (time_to_impact > 0.5) { return (FALSE); } if (get_local_entity_int_value (target, INT_TYPE_COLLISION_TEST_MOBILE)) { //////////////////////////////////////// // // MOBILE TARGET // //////////////////////////////////////// target_motion_vector = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_MOTION_VECTOR); sqr_velocity = ( target_motion_vector->x * target_motion_vector->x + target_motion_vector->y * target_motion_vector->y + target_motion_vector->z * target_motion_vector->z ); if (sqr_velocity > 1.0) { // // moving mobile // if (get_local_entity_int_value (target, INT_TYPE_UPDATED)) { get_local_entity_target_point (target, &target_new_position); target_old_position.x = target_new_position.x - target_motion_vector->x * get_delta_time (); target_old_position.y = target_new_position.y - target_motion_vector->y * get_delta_time (); target_old_position.z = target_new_position.z - target_motion_vector->z * get_delta_time (); } else { get_local_entity_target_point (target, &target_old_position); target_new_position.x = target_old_position.x + target_motion_vector->x * get_delta_time (); target_new_position.y = target_old_position.y + target_motion_vector->y * get_delta_time (); target_new_position.z = target_old_position.z + target_motion_vector->z * get_delta_time (); } if (get_3d_vector_cube_cube_intersect (weapon_old_position, weapon_new_position, &target_old_position, &target_new_position)) { line_line_3d_intercept ( weapon_old_position, weapon_new_position, &target_old_position, &target_new_position, &weapon_intercept_point, &target_intercept_point ); range = get_3d_range (&weapon_intercept_point, &target_intercept_point); if (range < COLLISION_THRESHOLD) { *weapon_new_position = weapon_intercept_point; return (TRUE); } } } else { // // stationary mobile // get_local_entity_target_point (target, &target_new_position); range = get_3d_perp_dist_of_point_from_line (weapon_old_position, weapon_new_position, &target_new_position, &weapon_intercept_point); if (range < COLLISION_THRESHOLD) { *weapon_new_position = weapon_intercept_point; return (TRUE); } } } else if (get_local_entity_int_value (target, INT_TYPE_COLLISION_TEST_FIXED)) { //////////////////////////////////////// // // FIXED TARGET // //////////////////////////////////////// get_local_entity_target_point (target, &target_new_position); range = get_3d_perp_dist_of_point_from_line (weapon_old_position, weapon_new_position, &target_new_position, &weapon_intercept_point); if (range < COLLISION_THRESHOLD) { *weapon_new_position = weapon_intercept_point; return (TRUE); } } return (FALSE); }