int attack_guide_find_best_weapon (entity *en) { entity *target, *aggressor; entity_sub_types best_weapon; // // check weapon // aggressor = get_local_entity_ptr_value (en, PTR_TYPE_TASK_LEADER); ASSERT (aggressor); target = get_local_entity_parent (aggressor, LIST_TYPE_TARGET); ASSERT (target); best_weapon = get_best_weapon_for_target (aggressor, target, BEST_WEAPON_RANGE_CHECK); if (best_weapon == ENTITY_SUB_TYPE_WEAPON_NO_WEAPON) { // // No suitable weapon at current range // best_weapon = get_best_weapon_for_target (aggressor, target, BEST_WEAPON_CRITERIA_MINIMAL); if (best_weapon == ENTITY_SUB_TYPE_WEAPON_NO_WEAPON) { // // Entity is not capable of destroying the target - abort the attack // delete_group_member_from_engage_guide (aggressor, en, TRUE); return FALSE; } } set_client_server_entity_int_value (aggressor, INT_TYPE_SELECTED_WEAPON, best_weapon); return TRUE; }
void initialise_attack_guide (entity *en) { entity *task, *aggressor, *target; ASSERT (en); task = get_local_entity_parent (en, LIST_TYPE_GUIDE); ASSERT (task); ASSERT (get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_TASK_ENGAGE); aggressor = get_local_entity_ptr_value (en, PTR_TYPE_TASK_LEADER); ASSERT (aggressor); target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT); ASSERT (target); if (!get_local_entity_int_value (aggressor, INT_TYPE_IDENTIFY_AIRCRAFT)) { // // Surface-Air & Surface-Surface // entity_sub_types best_weapon; // // find best weapon for target // best_weapon = get_best_weapon_for_target (aggressor, target, BEST_WEAPON_CRITERIA_ALL); set_client_server_entity_int_value (aggressor, INT_TYPE_SELECTED_WEAPON, best_weapon); return; } // // Air-Air & Air-Surface // if (get_local_entity_int_value (target, INT_TYPE_AIRBORNE_AIRCRAFT)) { initialise_air_to_air_attack_guide (en, aggressor, target); } else { initialise_air_to_ground_attack_guide (en, aggressor, target); } }
unsigned int assign_engage_tasks_to_group (entity *group, unsigned int valid_members) { entity *task, *guide, *target, *member, *single_member, *persuer, **guide_list; unsigned int member_number; int best_count, best_guide, loop, criteria, task_count, *assigned_count; float range, *priority; vec3d *member_pos, *target_pos; ASSERT (group); ASSERT (get_comms_model () == COMMS_MODEL_SERVER); if (!valid_members) { return valid_members; } // // count up engage tasks // task_count = 0; guide = get_local_entity_first_child (group, LIST_TYPE_GUIDE_STACK); while (guide) { if (get_local_entity_int_value (guide, INT_TYPE_VALID_GUIDE_MEMBERS) == TASK_ASSIGN_NO_MEMBERS) { task = get_local_entity_parent (guide, LIST_TYPE_GUIDE); ASSERT (task); ASSERT (get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_TASK_ENGAGE); if (get_local_entity_int_value (task, INT_TYPE_TASK_TERMINATED) == TASK_TERMINATED_IN_PROGRESS) { task_count ++; } } guide = get_local_entity_child_succ (guide, LIST_TYPE_GUIDE_STACK); } #if DEBUG_MODULE debug_log ("ENGAGE: =========================="); debug_log ("ENGAGE: %d suitable tasks", task_count); #endif if (task_count == 0) { return valid_members; } ////////////////////////////////////////////////////////////////// // // prioritize engage tasks // ////////////////////////////////////////////////////////////////// // // get target priority // guide_list = (entity * *) malloc_fast_mem (sizeof (entity *) * task_count); priority = (float *) malloc_fast_mem (sizeof (float) * task_count); assigned_count = (int *) malloc_fast_mem (sizeof (int) * task_count); #if DEBUG_MODULE debug_log ("ENGAGE: ======RAW LIST======"); #endif single_member = NULL; // check if we have a single member, if so assign that member to single_member for (member = get_local_entity_first_child (group, LIST_TYPE_MEMBER); member; member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER)) { member_number = (1 << get_local_entity_int_value (member, INT_TYPE_GROUP_MEMBER_NUMBER)); if (member_number & valid_members) { if (single_member) // we already have a valid member, so there is more than one { single_member = NULL; break; } else single_member = member; } } loop = 0; guide = get_local_entity_first_child (group, LIST_TYPE_GUIDE_STACK); while (guide) { if (get_local_entity_int_value (guide, INT_TYPE_VALID_GUIDE_MEMBERS) == TASK_ASSIGN_NO_MEMBERS) { task = get_local_entity_parent (guide, LIST_TYPE_GUIDE); ASSERT (task); ASSERT (get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_TASK_ENGAGE); if (get_local_entity_int_value (task, INT_TYPE_TASK_TERMINATED) == TASK_TERMINATED_IN_PROGRESS) { target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT); ASSERT (target); if (!target) { notify_local_entity (ENTITY_MESSAGE_TASK_TERMINATED, task, group, TASK_TERMINATED_ABORTED); free_mem (guide_list); free_mem (priority); free_mem (assigned_count); return valid_members; } guide_list [loop] = guide; if (get_local_entity_int_value (group, INT_TYPE_AIRCRAFT_GROUP)) { priority [loop] = get_local_entity_float_value (target, FLOAT_TYPE_TARGET_PRIORITY_AIR_ATTACK); } else { priority [loop] = get_local_entity_float_value (target, FLOAT_TYPE_TARGET_PRIORITY_GROUND_ATTACK); } #if DEBUG_MODULE debug_log ("ENGAGE: (%d) Target : %s, Priority %f", loop, get_local_entity_string (target, STRING_TYPE_FULL_NAME), priority [loop]); #endif loop ++; } } guide = get_local_entity_child_succ (guide, LIST_TYPE_GUIDE_STACK); } ASSERT (loop == task_count); // // sort the tasks according to their priority // quicksort_entity_list (guide_list, task_count, priority); #if DEBUG_MODULE debug_log ("ENGAGE: ======SORTED======"); for (loop = 0; loop < task_count; loop ++) { task = get_local_entity_parent (guide_list [loop], LIST_TYPE_GUIDE); target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT); debug_log ("ENGAGE: (%d) Target : %s (%d), Priority %f", loop, get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target), priority [loop]); } #endif // // consider other entities attacking the same targets // memset (assigned_count, 0, sizeof (int) * task_count); for (loop = 0; loop < task_count; loop ++) { task = get_local_entity_parent (guide_list [loop], LIST_TYPE_GUIDE); target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT); persuer = get_local_entity_first_child (target, LIST_TYPE_TARGET); while (persuer) { assigned_count [loop] ++; persuer = get_local_entity_child_succ (persuer, LIST_TYPE_TARGET); } } ////////////////////////////////////////////////////////////////// // // assign new engage tasks // // for each member, run through the task list (most important first) // try to assign one member per task, but as tasks run out group members can "team-up" // ////////////////////////////////////////////////////////////////// member = get_local_entity_first_child (group, LIST_TYPE_MEMBER); while ((member) && (valid_members)) { // // Only assign AI entities to ENGAGE tasks // if (get_local_entity_int_value (member, INT_TYPE_PLAYER) == ENTITY_PLAYER_AI) { if (get_local_entity_int_value (member, INT_TYPE_ENGAGE_ENEMY)) { member_number = (1 << get_local_entity_int_value (member, INT_TYPE_GROUP_MEMBER_NUMBER)); if (member_number & valid_members) { member_pos = get_local_entity_vec3d_ptr (member, VEC3D_TYPE_POSITION); if (get_local_entity_int_value (member, INT_TYPE_IDENTIFY_AIRCRAFT)) { criteria = BEST_WEAPON_CRITERIA_MINIMAL; } else { criteria = BEST_WEAPON_RANGE_CHECK | BEST_WEAPON_LOS_CHECK; } best_guide = -1; best_count = INT_MAX; for (loop = 0; loop < task_count; loop ++) { if (assigned_count [loop] < best_count) { guide = guide_list [loop]; task = get_local_entity_parent (guide, LIST_TYPE_GUIDE); target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT); if (target == member) { // // Don't try to attack yourself ! // continue; } // // Range Check // if (criteria & BEST_WEAPON_RANGE_CHECK) { // range handled by weapon selection range = 0.0; } else { target_pos = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION); range = get_sqr_2d_range (target_pos, member_pos); } if (range < MAX_ENGAGE_RANGE) { // // Weapon Check // if (get_best_weapon_for_target (member, target, criteria) != ENTITY_SUB_TYPE_WEAPON_NO_WEAPON) { best_count = assigned_count [loop]; best_guide = loop; } } } } if (best_guide != -1) { guide = guide_list [best_guide]; task = get_local_entity_parent (guide, LIST_TYPE_GUIDE); if (assign_new_task_to_group_member (group, member, task, NULL)) { valid_members &= (~member_number); assigned_count [best_guide] ++; #if DEBUG_MODULE debug_log ("ENGAGE: Assigning %s (%d) to target %s (%d)", get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member), get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target)); #endif } } else { #if DEBUG_MODULE debug_log ("ENGAGE: Couldn't assign %s (%d) to engage task", get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member)); #endif } } } } member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER); } free_mem (guide_list); free_mem (priority); free_mem (assigned_count); return valid_members; }