static void draw_local_3d_object (entity *en, float range) { fixed_wing *raw; day_segment_types day_segment_type; raw = (fixed_wing *) get_local_entity_data (en); // // update viewpoint // raw->ac.inst3d->vp.position = raw->ac.mob.position; memcpy (&raw->ac.inst3d->vp.attitude, &raw->ac.mob.attitude, sizeof (matrix3x3)); // // animate // animate_fixed_wing_afterburners (en); animate_fixed_wing_airbrakes (en); animate_fixed_wing_flaps (en); animate_fixed_wing_propellors (en); animate_aircraft_loading_doors (en); animate_aircraft_cargo_doors (en); animate_aircraft_undercarriage (en); animate_aircraft_weapon_system_ready (en); animate_aircraft_shadow (en); animate_aircraft_rudder (en); // // draw // day_segment_type = (day_segment_types) get_local_entity_int_value (get_session_entity (), INT_TYPE_DAY_SEGMENT_TYPE); raw->ac.inst3d->object_internal_lighting = ((day_segment_type == DAY_SEGMENT_TYPE_NIGHT) || (day_segment_type == DAY_SEGMENT_TYPE_DUSK)); raw->ac.inst3d->object_sprite_lights = (raw->ac.inst3d->object_internal_lighting && sprite_light_valid (en)); animate_and_draw_entity_muzzle_flash_effect (en); insert_object_into_3d_scene (OBJECT_3D_DRAW_TYPE_OBJECT, raw->ac.inst3d); #if DEBUG_MODULE if (en == get_external_view_entity ()) { vec3d *pos, wp_pos; draw_mobile_entity_debug_info (en); if (get_local_entity_primary_task (en)) { fixed_wing_movement_get_waypoint_position (en, &wp_pos); pos = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); create_debug_3d_line (pos, &wp_pos, sys_col_dark_green, 0.0); } } #endif }
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; }
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); } }
static void ship_movement_get_waypoint_position (entity *en, vec3d *wp_pos) { entity *wp, *group, *guide; float distance; vec3d *pos; ASSERT (en); ASSERT (wp_pos); group = get_local_entity_parent (en, LIST_TYPE_MEMBER); ASSERT (group); guide = get_local_entity_parent (en, LIST_TYPE_FOLLOWER); ASSERT (guide); wp = get_local_entity_parent (guide, LIST_TYPE_CURRENT_WAYPOINT); ASSERT (wp); // // Should vehicle follow leader, or follow guide in set waypoint formation? // if (get_local_entity_int_value (wp, INT_TYPE_MOBILE_FOLLOW_WAYPOINT_OFFSET)) { vec3d offset; get_local_entity_vec3d (guide, VEC3D_TYPE_GUIDE_POSITION, wp_pos); get_local_entity_formation_position_offset (en, wp, &offset); wp_pos->x += offset.x; wp_pos->y += offset.y; wp_pos->z += offset.z; } else { // // Task leader follows guide,.... other members follow task leader // if (get_local_entity_int_value (en, INT_TYPE_TASK_LEADER)) { get_local_entity_vec3d (guide, VEC3D_TYPE_GUIDE_POSITION, wp_pos); } else { // // set wp pos to offset from task leader // entity *task_leader; vec3d *xv, *leader_pos; formation_type *formation; int type, formation_count, formation_index, leader_formation_index; // // find task leader // task_leader = get_local_entity_ptr_value (guide, PTR_TYPE_TASK_LEADER); ASSERT (task_leader); // // get formation // type = get_local_entity_int_value (group, INT_TYPE_GROUP_FORMATION); formation = get_formation (type); formation_count = formation->number_in_formation; formation_index = get_local_entity_int_value (en, INT_TYPE_GROUP_MEMBER_NUMBER); leader_formation_index = get_local_entity_int_value (task_leader, INT_TYPE_GROUP_MEMBER_NUMBER); ASSERT (formation_index < formation_count); ASSERT (leader_formation_index < formation_count); // // calculate position // leader_pos = get_local_entity_vec3d_ptr (task_leader, VEC3D_TYPE_POSITION); xv = get_local_entity_vec3d_ptr (task_leader, VEC3D_TYPE_XV); // // take leader position and SUBTRACT leaders formation position (coz leader is not necessarily formation pos 0) // wp_pos->x = leader_pos->x - ((xv->x * formation->sites [leader_formation_index].x) + (xv->z * formation->sites [leader_formation_index].z)); wp_pos->y = 0; wp_pos->z = leader_pos->z - ((xv->z * formation->sites [leader_formation_index].x) + (xv->x * formation->sites [leader_formation_index].z)); // // then ADD members formation position // wp_pos->x += ((xv->x * formation->sites [formation_index].x) + (xv->z * formation->sites [formation_index].z)); wp_pos->z += ((xv->z * formation->sites [formation_index].x) + (xv->x * formation->sites [formation_index].z)); } } // // calculate distance of entity to desired position // pos = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); distance = get_2d_range (pos, wp_pos); #if DEBUG_WAYPOINT_VECTOR if (distance > 0.0) { create_debug_3d_line (pos, wp_pos, sys_col_black, 0.0); } #endif set_local_entity_float_value (en, FLOAT_TYPE_DISTANCE, distance); }