int get_angle_of_projection (const vec3d *source, const vec3d *target, float velocity, float *angle_of_projection) { if (velocity > 0.001) { float range = get_2d_range (source, target); return get_angle_of_projection_with_range(source, target, velocity, angle_of_projection, range); } else return FALSE; }
void update_waypoint_shared_mem() { entity* wp; if (!gPtrSharedMemory || !get_gunship_entity()) return; wp = get_local_entity_current_waypoint(get_gunship_entity()); if (wp) { vec3d *gunship_position, waypoint_position; float dx, dz, bearing; gunship_position = get_local_entity_vec3d_ptr(get_gunship_entity(), VEC3D_TYPE_POSITION); get_waypoint_display_position (get_gunship_entity(), wp, &waypoint_position); gPtrSharedMemory->waypoint_data.waypoint = get_local_entity_char_value(wp, CHAR_TYPE_TAG); gPtrSharedMemory->waypoint_data.waypoint_range = get_2d_range (gunship_position, &waypoint_position); dx = waypoint_position.x - gunship_position->x; dz = waypoint_position.z - gunship_position->z; bearing = deg(atan2(dx, dz)); if (bearing < 0.0) bearing += 360.0; gPtrSharedMemory->waypoint_data.waypoint_bearing = bearing; } else memset(&gPtrSharedMemory->waypoint_data, 0, sizeof(waypoint_data_t)); }
aircraft_fire_result aircraft_fire_weapon (entity *en, unsigned int check_flags) { entity *target; aircraft *raw; vec3d *target_pos, en_pos; int loal_mode = FALSE; ASSERT (en); raw = (aircraft *) get_local_entity_data (en); // // Fire suppressed // if (check_flags & AIRCRAFT_FIRE_SUPPRESSED) { if (get_local_entity_int_value (get_session_entity (), INT_TYPE_SUPPRESS_AI_FIRE)) { return AIRCRAFT_FIRE_SUPPRESSED; } } // // check weapon // if (check_flags & AIRCRAFT_FIRE_NO_WEAPON) { if (get_local_entity_int_value (en, INT_TYPE_SELECTED_WEAPON) == ENTITY_SUB_TYPE_WEAPON_NO_WEAPON) { debug_log ("AC_WPN: Fire Weapon Error - NO WEAPON"); return AIRCRAFT_FIRE_NO_WEAPON; } } // // weapon system_ready // if (check_flags & AIRCRAFT_FIRE_WEAPON_SYSTEM_NOT_READY) { if (!get_local_entity_int_value (en, INT_TYPE_SELECTED_WEAPON_SYSTEM_READY)) { debug_log ("AC_WPN: Fire Weapon Error - WEAPON SYSTEM NOT READY"); return AIRCRAFT_FIRE_WEAPON_SYSTEM_NOT_READY; } } // debug_log("%s: %d", get_sub_type_name(en), get_local_entity_int_value (en, INT_TYPE_SELECTED_WEAPON)); // // find target // if (check_flags & AIRCRAFT_FIRE_NO_TARGET) { target = get_local_entity_parent (en, LIST_TYPE_TARGET); if (!target) { debug_log ("AC_WPN: Fire Weapon Error - NO TARGET"); return AIRCRAFT_FIRE_NO_TARGET; } } // // line of sight checks // if (check_flags & AIRCRAFT_FIRE_NO_LOS) { int criteria; if (get_local_entity_int_value (target, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI) { criteria = MOBILE_LOS_CHECK_ALL; } else { criteria = MOBILE_LOS_CHECK_COURSE_TERRAIN; } get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &en_pos); target_pos = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION); en_pos.y -= (get_local_entity_float_value (en, FLOAT_TYPE_CENTRE_OF_GRAVITY_TO_GROUND_DISTANCE) + 2.0); if (!check_position_line_of_sight (en, target, &en_pos, target_pos, (mobile_los_check_criteria) criteria)) { if (get_local_entity_int_value (en, INT_TYPE_SELECTED_WEAPON) == ENTITY_SUB_TYPE_WEAPON_AGM114L_LONGBOW_HELLFIRE && get_2d_range(&en_pos, target_pos) > weapon_database[ENTITY_SUB_TYPE_WEAPON_AGM114L_LONGBOW_HELLFIRE].min_range_loal) { debug_log("AC_WPN: Switching to LOAL mode to fire at target without LOS ((Aircraft %s (%d), Target %s (%d))", get_local_entity_string (en, STRING_TYPE_FULL_NAME), get_local_entity_index (en), get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target)); loal_mode = TRUE; } else { debug_log ("AC_WPN: Fire Weapon Error - NO LOS (Aircraft %s (%d), Target %s (%d))", get_local_entity_string (en, STRING_TYPE_FULL_NAME), get_local_entity_index (en), get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target)); return AIRCRAFT_FIRE_NO_LOS; } } } // // Play Speech // play_aircraft_weapon_launched_speech (en, raw->selected_weapon); // // Fire weapon // set_local_entity_int_value(en, INT_TYPE_LOCK_ON_AFTER_LAUNCH, loal_mode); launch_client_server_weapon (en, raw->selected_weapon); return AIRCRAFT_FIRE_OK; }
void group_return_to_base (entity *en) { entity *wp, *guide, *last_wp, *best_wp, *obj_wp, *current_wp; vec3d *pos, *wp_pos, *last_pos, normal; float d, range, best_range; int s, sub_type; debug_log ("GROUP: sending group %s (%d) home... ", get_local_entity_string (en, STRING_TYPE_FULL_NAME), get_local_entity_index (en)); // // Abort all engage tasks // terminate_all_engage_tasks (en); // // Find group position // pos = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); // // find objective wp, and last wp position // obj_wp = NULL; guide = get_local_group_primary_guide (en); ASSERT (guide); current_wp = get_local_entity_parent (guide, LIST_TYPE_CURRENT_WAYPOINT); ASSERT (current_wp); wp = current_wp; while (get_local_entity_child_succ (wp, LIST_TYPE_WAYPOINT)) { wp = get_local_entity_child_succ (wp, LIST_TYPE_WAYPOINT); sub_type = get_local_entity_int_value (wp, INT_TYPE_ENTITY_SUB_TYPE); if (waypoint_database [sub_type].objective_waypoint) { obj_wp = wp; } } last_wp = wp; last_pos = get_local_entity_vec3d_ptr (last_wp, VEC3D_TYPE_POSITION); if (current_wp == last_wp) { return; } // // Check each waypoint after the objective waypoint (if obj_wp is NULL then the group has already passed the objective wp // or there isn't one) // if (!obj_wp) { obj_wp = current_wp; } // // Find vector of group to last wp // normal.x = last_pos->x - pos->x; normal.y = 0.0; normal.z = last_pos->z - pos->z; if (normalise_any_3d_vector (&normal) == 0.0) { return; } // // Test sign of last position // d = ((last_pos->x * normal.x) + (last_pos->z * normal.z)) - ((pos->x * normal.x) + (pos->z * normal.z)); s = sign (d); // // find closest waypoint heading back towards the last waypoint // wp = get_local_entity_child_succ (obj_wp, LIST_TYPE_WAYPOINT); ASSERT (wp); best_wp = last_wp; best_range = FLT_MAX; while (wp) { wp_pos = get_local_entity_vec3d_ptr (wp, VEC3D_TYPE_POSITION); d = ((wp_pos->x * normal.x) + (wp_pos->z * normal.z)) - ((pos->x * normal.x) + (pos->z * normal.z)); if (sign (d) == s) { range = get_2d_range (wp_pos, pos); if (range < best_range) { best_wp = wp; best_range = range; } } wp = get_local_entity_child_succ (wp, LIST_TYPE_WAYPOINT); } // // set guide to best waypoint // set_guide_new_waypoint (guide, best_wp); }
int amalgamate_groups (entity *receiving_group, entity *donating_group) { entity *this_member, *member; int group_type, group_kills, group_losses, donating_group_count, receiving_group_count; ASSERT (get_comms_model () == COMMS_MODEL_SERVER); // check both groups are not doing any tasks ASSERT (get_local_entity_int_value (receiving_group, INT_TYPE_GROUP_MODE) == GROUP_MODE_IDLE); ASSERT (get_local_entity_int_value (donating_group, INT_TYPE_GROUP_MODE) == GROUP_MODE_IDLE); // check group type are the same group_type = get_local_entity_int_value (receiving_group, INT_TYPE_ENTITY_SUB_TYPE); if (group_type != get_local_entity_int_value (donating_group, INT_TYPE_ENTITY_SUB_TYPE)) { return FALSE; } ASSERT (group_database [group_type].amalgamate); ASSERT (get_local_entity_int_value (donating_group, INT_TYPE_SIDE) == get_local_entity_int_value (receiving_group, INT_TYPE_SIDE)); donating_group_count = get_local_entity_int_value (donating_group, INT_TYPE_MEMBER_COUNT); receiving_group_count = get_local_entity_int_value (receiving_group, INT_TYPE_MEMBER_COUNT); if ((donating_group_count + receiving_group_count) <= group_database [group_type].maximum_member_count) { #ifdef DEBUG //#if DEBUG_MODULE if ((get_local_entity_parent (donating_group, LIST_TYPE_KEYSITE_GROUP)) && (get_local_entity_parent (receiving_group, LIST_TYPE_KEYSITE_GROUP))) { ASSERT (get_local_entity_type (get_local_entity_parent (donating_group, LIST_TYPE_KEYSITE_GROUP)) == get_local_entity_type (get_local_entity_parent (receiving_group, LIST_TYPE_KEYSITE_GROUP))); } debug_log ("GROUP: amalgamating group %s %d (count %d) with group %s %d (count %d)", entity_sub_type_group_names [group_type], get_local_entity_index (donating_group), donating_group_count, entity_sub_type_group_names [group_type], get_local_entity_index (receiving_group), receiving_group_count); member = get_local_entity_first_child (donating_group, LIST_TYPE_MEMBER); while (member) { debug_log ("GROUP: donating group member %s (%d)", get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member)); ASSERT (get_local_entity_int_value (member, INT_TYPE_OPERATIONAL_STATE) == OPERATIONAL_STATE_LANDED); member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER); } member = get_local_entity_first_child (receiving_group, LIST_TYPE_MEMBER); while (member) { debug_log ("GROUP: receiving group member %s (%d)", get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member)); ASSERT (get_local_entity_int_value (member, INT_TYPE_OPERATIONAL_STATE) == OPERATIONAL_STATE_LANDED); member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER); } //#endif #endif member = get_local_entity_first_child (donating_group, LIST_TYPE_MEMBER); while (member) { this_member = member; member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER); set_client_server_entity_parent (this_member, LIST_TYPE_MEMBER, receiving_group); } group_kills = get_local_entity_int_value (receiving_group, INT_TYPE_KILLS); group_losses = get_local_entity_int_value (receiving_group, INT_TYPE_LOSSES); group_kills += get_local_entity_int_value (donating_group, INT_TYPE_KILLS); group_losses += get_local_entity_int_value (donating_group, INT_TYPE_LOSSES); if (get_local_entity_int_value (receiving_group, INT_TYPE_KILLS) != group_kills) { set_client_server_entity_int_value (receiving_group, INT_TYPE_KILLS, group_kills); } if (get_local_entity_int_value (receiving_group, INT_TYPE_LOSSES) != group_losses) { set_client_server_entity_int_value (receiving_group, INT_TYPE_LOSSES, group_losses); } // // renumber the group members // set_group_member_numbers (receiving_group); // // place empty donating group on free list // ASSERT (get_local_entity_int_value (donating_group, INT_TYPE_MEMBER_COUNT) == 0); kill_client_server_group_entity (donating_group); #ifdef DEBUG { vec3d *pos1, *test_pos; float amalgamate_max_range = 10 * KILOMETRE; member = get_local_entity_first_child (receiving_group, LIST_TYPE_MEMBER); ASSERT (member); pos1 = get_local_entity_vec3d_ptr (member, VEC3D_TYPE_POSITION); member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER); while (member) { test_pos = get_local_entity_vec3d_ptr (member, VEC3D_TYPE_POSITION); if (get_2d_range (pos1, test_pos) > amalgamate_max_range) { debug_log ("GROUP: WARNING: Amalgamated group with members (%s (%d) and %s (%d)) %f apart -------------------------", get_local_entity_string (get_local_entity_first_child (receiving_group, LIST_TYPE_MEMBER), STRING_TYPE_FULL_NAME), get_local_entity_index (get_local_entity_first_child (receiving_group, LIST_TYPE_MEMBER)), get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member), get_2d_range (pos1, test_pos)); } member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER); } } #endif return TRUE; } return FALSE; }
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); }
entity *get_closest_waypoint (entity *task, vec3d *pos, float min_range, float *actual_range) { float best_range, range; vec3d *waypoint_pos; entity *closest_waypoint = NULL, *current_waypoint; best_range = 99999999; current_waypoint = get_local_entity_first_child (task, LIST_TYPE_WAYPOINT); while (current_waypoint) { waypoint_pos = get_local_entity_vec3d_ptr (current_waypoint, VEC3D_TYPE_POSITION); range = get_approx_2d_range (waypoint_pos, pos); if (actual_range) { *actual_range = range; } if (range <= min_range) { #if LANDING_DEBUG >= 2 debug_log ("AI_MISC: EARLY OUT: found waypoint %d (type %d) range %f", current_waypoint, entity_sub_type_waypoint_names [get_local_entity_int_value (current_waypoint, INT_TYPE_ENTITY_SUB_TYPE)], range); #endif return current_waypoint; } if (range < best_range) { best_range = range; closest_waypoint = current_waypoint; #if LANDING_DEBUG debug_log ("AI_MISC: found waypoint %d (type %d) range %f", current_keysite, entity_sub_type_waypoint_names [get_local_entity_int_value (current_waypoint, INT_TYPE_ENTITY_SUB_TYPE)], range); #endif } current_waypoint = get_local_entity_child_succ (current_waypoint, LIST_TYPE_WAYPOINT); } if ( closest_waypoint ) { waypoint_pos = get_local_entity_vec3d_ptr (closest_waypoint, VEC3D_TYPE_POSITION); best_range = get_2d_range (waypoint_pos, pos); } if (actual_range) { *actual_range = best_range; } return closest_waypoint; }
entity *get_closest_halfway_waypoint (entity *task, vec3d *pos, float min_range, float *actual_range) { float best_range, range; vec3d *waypoint_pos1, *waypoint_pos2, mid_pos; entity *closest_waypoint = NULL, *waypoint1, *waypoint2; best_range = 99999999; waypoint1 = get_local_entity_first_child (task, LIST_TYPE_WAYPOINT); waypoint2 = get_local_entity_child_succ (waypoint1, LIST_TYPE_WAYPOINT); while (waypoint2) { waypoint_pos1 = get_local_entity_vec3d_ptr (waypoint1, VEC3D_TYPE_POSITION); waypoint_pos2 = get_local_entity_vec3d_ptr (waypoint2, VEC3D_TYPE_POSITION); mid_pos.x = waypoint_pos1->x + ( ( waypoint_pos2->x - waypoint_pos1->x ) / 2 ); mid_pos.y = waypoint_pos1->y + ( ( waypoint_pos2->y - waypoint_pos1->y ) / 2 ); mid_pos.z = waypoint_pos1->z + ( ( waypoint_pos2->z - waypoint_pos1->z ) / 2 ); range = get_approx_2d_range (&mid_pos, pos); if (range < best_range) { best_range = range; closest_waypoint = waypoint1; } waypoint1 = waypoint2; waypoint2 = get_local_entity_child_succ (waypoint2, LIST_TYPE_WAYPOINT); } if ( closest_waypoint ) { waypoint1 = closest_waypoint; waypoint2 = get_local_entity_child_succ (waypoint1, LIST_TYPE_WAYPOINT); waypoint_pos1 = get_local_entity_vec3d_ptr (waypoint1, VEC3D_TYPE_POSITION); waypoint_pos2 = get_local_entity_vec3d_ptr (waypoint2, VEC3D_TYPE_POSITION); mid_pos.x = waypoint_pos1->x + ( ( waypoint_pos2->x - waypoint_pos1->x ) / 2 ); mid_pos.y = waypoint_pos1->y + ( ( waypoint_pos2->y - waypoint_pos1->y ) / 2 ); mid_pos.z = waypoint_pos1->z + ( ( waypoint_pos2->z - waypoint_pos1->z ) / 2 ); best_range = get_2d_range (&mid_pos, pos); } if (actual_range) { *actual_range = best_range; } return ( closest_waypoint ); }