int group_task_specific_retaliation_checks (entity *group, entity *aggressor, int assisted) { entity *task, *objective; task_roe_types roe; entity_sides side; vec3d *group_pos, *objective_pos, *aggressor_pos; int sx, sz; ASSERT (get_comms_model () == COMMS_MODEL_SERVER); ASSERT (group); ASSERT (aggressor); if (get_local_entity_int_value (group, INT_TYPE_AIRCRAFT_GROUP)) { task = get_local_group_primary_task (group); if (!task) { return FALSE; } if (get_local_entity_int_value (aggressor, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI) { return TRUE; } roe = get_local_entity_int_value (task, INT_TYPE_RULES_OF_ENGAGEMENT); switch (roe) { case TASK_ROE_NONE: { // // FALSE if aggressor is within target area (stop RECON missions from destroying objectives) // if (get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_TASK_RECON) { objective = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT); if (objective) { objective_pos = get_local_entity_vec3d_ptr (objective, VEC3D_TYPE_POSITION); ASSERT (objective_pos); aggressor_pos = get_local_entity_vec3d_ptr (aggressor, VEC3D_TYPE_POSITION); ASSERT (aggressor_pos); if (get_sqr_2d_range (aggressor_pos, objective_pos) < ((2.0 * KILOMETRE) * (2.0 * KILOMETRE))) { ai_log ("(RETALIATE CHECK) ROE NONE - Failed (Aggressor at target area)"); return FALSE; } } } // // Retaliate if no-one else coming to assist, AND (mission complete OR aggressor in friendly territory) // if (!assisted) { if (get_local_entity_int_value (task, INT_TYPE_TASK_COMPLETED) != TASK_INCOMPLETE) { ai_log ("(RETALIATE CHECK) ROE NONE - Task Complete"); return TRUE; } side = get_local_entity_int_value (group, INT_TYPE_SIDE); group_pos = get_local_entity_vec3d_ptr (group, VEC3D_TYPE_POSITION); ASSERT (group_pos); get_x_sector (sx, group_pos->x); get_z_sector (sz, group_pos->z); if (get_local_sector_side_ratio (sx, sz, side) > 0.5) { ai_log ("(RETALIATE CHECK) ROE NONE - Friendly Territory"); return TRUE; } } ai_log ("(RETALIATE CHECK) ROE NONE - Failed Checks"); break; } case TASK_ROE_OBJECTIVE: { // // Retaliate if no-one else coming to assist, OR primary task completed // if (!assisted) { ai_log ("(RETALIATE CHECK) ROE OBJECTIVE - No Assistance"); return TRUE; } if (get_local_entity_int_value (task, INT_TYPE_TASK_COMPLETED) != TASK_INCOMPLETE) { ai_log ("(RETALIATE CHECK) ROE OBJECTIVE - Task Complete"); return TRUE; } ai_log ("(RETALIATE CHECK) ROE OBJECTIVE - Failed Checks"); break; } case TASK_ROE_ALL: { // // Always retaliate // ai_log ("(RETALIATE CHECK) ROE ALL"); return TRUE; } } return FALSE; } else { return TRUE; } }
void assign_keysite_tasks (entity *keysite, task_category_types category) { entity *task, *group, *force, **task_list; float *sort_order; int loop, task_type, task_count, assign_count, group_type, keysite_type, non_critical_task_count; static int idle_group_count [NUM_ENTITY_SUB_TYPE_GROUPS]; ASSERT (keysite); ASSERT (get_comms_model () == COMMS_MODEL_SERVER); task = get_local_entity_first_child (keysite, LIST_TYPE_UNASSIGNED_TASK); if (!task) { return; } keysite_type = get_local_entity_int_value (keysite, INT_TYPE_ENTITY_SUB_TYPE); force = get_local_entity_parent (keysite, LIST_TYPE_KEYSITE_FORCE); ASSERT (force); // // Count tasks at keysite // task_count = 0; task = get_local_entity_first_child (keysite, LIST_TYPE_UNASSIGNED_TASK); while (task) { if (get_local_entity_int_value (task, INT_TYPE_TASK_CATEGORY) == category) { task_count ++; } task = get_local_entity_child_succ (task, LIST_TYPE_UNASSIGNED_TASK); } if (task_count == 0) { return; } // // Count up number of idle groups across the map (air registry only) // memset (idle_group_count, 0, sizeof (int) * NUM_ENTITY_SUB_TYPE_GROUPS); group = get_local_entity_first_child (force, LIST_TYPE_AIR_REGISTRY); while (group) { if (get_local_entity_int_value (group, INT_TYPE_GROUP_MODE) == GROUP_MODE_IDLE) { group_type = get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE); idle_group_count [group_type] ++; } group = get_local_entity_child_succ (group, LIST_TYPE_AIR_REGISTRY); } // // Sort tasks // ASSERT (task_count > 0); task_list = ( entity * * ) malloc_fast_mem (sizeof (entity *) * task_count); sort_order = ( float * ) malloc_fast_mem (sizeof (float) * task_count); task_count = 0; task = get_local_entity_first_child (keysite, LIST_TYPE_UNASSIGNED_TASK); while (task) { if (get_local_entity_int_value (task, INT_TYPE_TASK_CATEGORY) == category) { task_list [task_count] = task; sort_order [task_count] = get_local_entity_float_value (task, FLOAT_TYPE_TASK_PRIORITY); if (get_local_entity_int_value (task, INT_TYPE_CRITICAL_TASK)) { sort_order [task_count] *= 2.0; } task_count ++; } task = get_local_entity_child_succ (task, LIST_TYPE_UNASSIGNED_TASK); } quicksort_entity_list (task_list, task_count, sort_order); // // Assign tasks // assign_count = max (keysite_database [keysite_type].assign_task_count, 1u); non_critical_task_count = keysite_database [keysite_type].reserve_task_count; for (loop = 0; loop < task_count; loop ++) { if (assign_count == 0) { break; } task = task_list [loop]; // // Check for player lock // if (get_local_entity_parent (task, LIST_TYPE_PILOT_LOCK)) { continue; } // // Reserve non-critical tasks for player // if (!get_local_entity_int_value (task, INT_TYPE_CRITICAL_TASK)) { if (get_local_entity_float_value (task, FLOAT_TYPE_EXPIRE_TIMER) > KEYSITE_TASK_ASSIGN_TIMER) { if (non_critical_task_count > 0) { non_critical_task_count --; continue; } } } task_type = get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE); group = get_suitable_registered_group (task, idle_group_count); if (group) { if (assign_primary_task_to_group (group, task)) { ai_log ("ASSIGN: (%d/%d) Assigned group %s (%d) to task %s (%d) from keysite %s (%s)", assign_count, keysite_database [keysite_type].assign_task_count, entity_sub_type_group_names [get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE)], get_local_entity_index (group), entity_sub_type_task_names [task_type], get_local_entity_index (task), get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME), entity_side_short_names [get_local_entity_int_value (keysite, INT_TYPE_SIDE)]); // // Only Assign n tasks per keysite // assign_count --; } else { #if DEBUG_MODULE debug_log ("ASSIGN: not assigning group %s (%d) to task %s (%d) from keysite %s", entity_sub_type_group_names [get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE)], get_local_entity_index (group), entity_sub_type_task_names [task_type], get_local_entity_index (task), get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME)); #endif } } } free_mem (task_list); free_mem (sort_order); }
int create_group_emergency_transfer_task (entity *en) { entity *landing, *new_keysite, *new_task; int side, landing_type, sites_required; vec3d *pos; ASSERT (en); ASSERT (get_comms_model () == COMMS_MODEL_SERVER); side = get_local_entity_int_value (en, INT_TYPE_SIDE); pos = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); group_terminate_all_tasks (en); sites_required = get_local_group_member_count (en); landing_type = group_database [get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE)].default_landing_type; landing = get_closest_free_landing_site (landing_type, get_local_force_entity (side), pos, 0.0, NULL, sites_required); if (landing) { // // Found new keysite // new_keysite = get_local_entity_parent (landing, LIST_TYPE_LANDING_SITE); if (landing_type == ENTITY_SUB_TYPE_LANDING_HELICOPTER) { new_task = create_transfer_task (side, ENTITY_SUB_TYPE_TASK_TRANSFER_HELICOPTER, 10.0, new_keysite, new_keysite); } else { new_task = create_transfer_task (side, ENTITY_SUB_TYPE_TASK_TRANSFER_FIXED_WING, 10.0, new_keysite, new_keysite); } ASSERT (new_task); if (!assign_primary_task_to_group (en, new_task)) { // // Failed to assign transfer task // ai_log ("(TRANSFER) Failed to assign Emergency Transfer to %s", get_local_entity_string (en, STRING_TYPE_FULL_NAME)); group_kill_all_members (en); return FALSE; } else { ai_log ("(TRANSFER) Successfully assigned Emergency Transfer to %s", get_local_entity_string (en, STRING_TYPE_FULL_NAME)); return TRUE; } } else { // // Failed to find alternate keysite // ai_log ("(TRANSFER) Failed to find Emergency Transfer keysite for %s", get_local_entity_string (en, STRING_TYPE_FULL_NAME)); group_kill_all_members (en); return FALSE; } }
int assign_primary_task_to_group (entity *group_en, entity *task_en) { entity_sub_types task_type, group_type; entity *force, *keysite; int side, formation, air_threat, enemy_sectors; unsigned int threat; ASSERT (get_comms_model () == COMMS_MODEL_SERVER); task_type = get_local_entity_int_value (task_en, INT_TYPE_ENTITY_SUB_TYPE); ASSERT (task_database [task_type].primary_task); group_type = get_local_entity_int_value (group_en, INT_TYPE_ENTITY_SUB_TYPE); ASSERT (!get_local_group_primary_task (group_en)); if (assign_task_to_group (group_en, task_en, TASK_ASSIGN_ALL_MEMBERS)) { // // set default group formation // formation = get_local_entity_int_value (group_en, INT_TYPE_GROUP_DEFAULT_FORMATION); if (formation != get_local_entity_int_value (group_en, INT_TYPE_GROUP_FORMATION)) { set_client_server_entity_int_value (group_en, INT_TYPE_GROUP_FORMATION, formation); } // // Link to new keysite // if (get_local_entity_int_value (group_en, INT_TYPE_GROUP_LIST_TYPE) == LIST_TYPE_KEYSITE_GROUP) { keysite = ( entity * ) get_local_entity_ptr_value (task_en, PTR_TYPE_RETURN_KEYSITE); if (keysite) { set_client_server_entity_parent (group_en, LIST_TYPE_KEYSITE_GROUP, keysite); } } // // Notify Force // side = get_local_entity_int_value (group_en, INT_TYPE_SIDE); force = get_local_force_entity ( ( entity_sides ) side ); ASSERT (force); notify_local_entity (ENTITY_MESSAGE_TASK_ASSIGNED, force, task_en); // // Assess for Escort task // if (task_database [task_type].escort_required_threshold != ESCORT_NEVER) { threat = assess_task_difficulty (task_en, &air_threat, &enemy_sectors); #if DEBUG_ESCORT_TASK_CREATION debug_filtered_log ("(ASSIGN) Side %s: Assigned %s to %s, objective %s", entity_side_short_names [side], get_local_entity_string (group_en, STRING_TYPE_FULL_NAME), get_local_entity_string (task_en, STRING_TYPE_FULL_NAME), get_task_objective_string (task_en) ); debug_filtered_log ("Threat: %d (air_threat: %d, enemy_sectors: %d) - Threshold %d", threat, air_threat, enemy_sectors, task_database [task_type].escort_required_threshold); #endif if (threat >= task_database [task_type].escort_required_threshold) { create_escort_task (group_en, (threat >= ESCORT_CRITICAL), task_database [ENTITY_SUB_TYPE_TASK_ESCORT].task_priority, NULL, NULL); ai_log ("(ASSIGN) Created Escort Task for %s :- Threat %d / Threshold %d", get_local_entity_string (task_en, STRING_TYPE_FULL_NAME), threat, task_database [task_type].escort_required_threshold ); } } // // Store Start Time // set_client_server_entity_float_value (task_en, FLOAT_TYPE_START_TIME, get_local_entity_float_value (get_session_entity (), FLOAT_TYPE_ELAPSED_TIME)); // // Clear Expire Timer (now also used for destroying completed tasks) // set_local_entity_float_value (task_en, FLOAT_TYPE_EXPIRE_TIMER, 0.0); ai_log ("(ASSIGN) Side %s: Assigned %s (%d) to %s (%d) - Priority %f", entity_side_short_names [side], get_local_entity_string (group_en, STRING_TYPE_FULL_NAME), get_local_entity_safe_index (group_en), get_local_entity_string (task_en, STRING_TYPE_FULL_NAME), get_local_entity_safe_index (task_en), get_local_entity_float_value (task_en, FLOAT_TYPE_TASK_PRIORITY)); return TRUE; } return FALSE; }