entity *add_group_to_division (entity *group, entity *specified_division) { entity_sides side; int count, max_count, group_type, keysite_type, division_type, main_division_type; entity *en, *force, *keysite, *division; vec3d *group_pos; ASSERT (group); ASSERT (get_comms_model () == COMMS_MODEL_SERVER); ASSERT (!get_local_entity_parent (group, LIST_TYPE_DIVISION)); group_type = get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE); group_pos = get_local_entity_vec3d_ptr (group, VEC3D_TYPE_POSITION); if (specified_division) { division = specified_division; } else { side = (entity_sides) get_local_entity_int_value (group, INT_TYPE_SIDE); force = get_local_force_entity (side); ASSERT (force); division_type = group_database [group_type].default_group_division; ASSERT (entity_sub_type_division_valid (division_type)); main_division_type = division_database [division_type].default_group_division; ASSERT (entity_sub_type_division_valid (main_division_type)); // // Find the keysite the company should be attached to // keysite = NULL; if (get_local_entity_int_value (group, INT_TYPE_GROUP_LIST_TYPE) == LIST_TYPE_KEYSITE_GROUP) { keysite = get_local_entity_parent (group, LIST_TYPE_KEYSITE_GROUP); if (!keysite) { keysite = get_closest_keysite (NUM_ENTITY_SUB_TYPE_KEYSITES, side, group_pos, 1.0 * KILOMETRE, NULL, NULL); } ASSERT (keysite); keysite_type = get_local_entity_int_value (keysite, INT_TYPE_ENTITY_SUB_TYPE); if ((keysite_type == ENTITY_SUB_TYPE_KEYSITE_AIRBASE) || (keysite_type == ENTITY_SUB_TYPE_KEYSITE_ANCHORAGE)) { // // Use keysite landed at // } else { // // Find nearest keysite (below) // keysite = NULL; } } else { if (group_database [group_type].movement_type == MOVEMENT_TYPE_SEA) { // // Find nearest carrier // keysite = get_closest_keysite (ENTITY_SUB_TYPE_KEYSITE_ANCHORAGE, side, group_pos, 0.0, NULL, NULL); } } if (!keysite) { // // Find nearest airbase // keysite = get_closest_keysite (ENTITY_SUB_TYPE_KEYSITE_AIRBASE, side, group_pos, 0.0, NULL, NULL); if (!keysite) { // // Find nearest military base // keysite = get_closest_keysite (ENTITY_SUB_TYPE_KEYSITE_MILITARY_BASE, side, group_pos, 0.0, NULL, NULL); if (!keysite) { // // Find nearest FARP // keysite = get_closest_keysite (ENTITY_SUB_TYPE_KEYSITE_FARP, side, group_pos, 0.0, NULL, NULL); } } } ASSERT (keysite); // // Check all companies at this keysite to see if they have vacancies.... // max_count = group_database [group_type].maximum_groups_per_division; division = get_local_entity_first_child (keysite, LIST_TYPE_DIVISION_HEADQUARTERS); while (division) { if (get_local_entity_int_value (division, INT_TYPE_ENTITY_SUB_TYPE) == division_type) { if (max_count == 0) { break; } count = 0; en = get_local_entity_first_child (division, LIST_TYPE_DIVISION); while (en) { ASSERT (get_local_entity_type (en) == ENTITY_TYPE_GROUP); count ++; en = get_local_entity_child_succ (en, LIST_TYPE_DIVISION); } if (count < max_count) { break; } } division = get_local_entity_child_succ (division, LIST_TYPE_DIVISION_HEADQUARTERS); } if (division) { // // found an existing division with space available // } else { // // create a new division // entity *main_division; max_count = division_database [division_type].maximum_groups_per_division; main_division = get_local_entity_first_child (force, LIST_TYPE_DIVISION); while (main_division) { if (get_local_entity_int_value (main_division, INT_TYPE_ENTITY_SUB_TYPE) == main_division_type) { // // check division for vacancies // if (max_count == 0) { break; } count = 0; en = get_local_entity_first_child (main_division, LIST_TYPE_DIVISION); while (en) { ASSERT (get_local_entity_type (en) == ENTITY_TYPE_DIVISION); if (get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE) == division_type) { count ++; } en = get_local_entity_child_succ (en, LIST_TYPE_DIVISION); } if (count < max_count) { break; } } main_division = get_local_entity_child_succ (main_division, LIST_TYPE_DIVISION); } if (main_division) { // // found an existing division with space available // } else { // // create a new division // main_division = create_new_division (main_division_type, side, force, NULL, FALSE); } ASSERT (main_division); division = create_new_division (division_type, side, main_division, keysite, FALSE); } } ASSERT (division); set_client_server_entity_parent (group, LIST_TYPE_DIVISION, division); return division; }
void create_force_campaign_objectives (entity *force) { entity *keysite, *target_force, **list; int loop, count, side, target_side; float highest, *rating; ASSERT (get_comms_model () == COMMS_MODEL_SERVER); ASSERT (get_session_entity ()); ASSERT (force); side = get_local_entity_int_value (force, INT_TYPE_SIDE); // // count up potential objective keysites // count = 0; target_force = get_local_entity_first_child (get_session_entity (), LIST_TYPE_FORCE); while (target_force) { if (target_force != force) { keysite = get_local_entity_first_child (target_force, LIST_TYPE_KEYSITE_FORCE); while (keysite) { if (get_local_entity_int_value (keysite, INT_TYPE_POTENTIAL_CAMPAIGN_OBJECTIVE)) { if (get_local_entity_int_value (keysite, INT_TYPE_IN_USE)) { count ++; } } keysite = get_local_entity_child_succ (keysite, LIST_TYPE_KEYSITE_FORCE); } } target_force = get_local_entity_child_succ (target_force, LIST_TYPE_FORCE); } if (count == 0) { debug_fatal ("SETUP: No potential campaign objectives for side %s", entity_side_short_names [side]); } // // construct the list and rate each keysite according to sector importance // list = malloc_heap_mem (sizeof (entity *) * count); rating = malloc_heap_mem (sizeof (float) * count); highest = 0.0; count = 0; target_force = get_local_entity_first_child (get_session_entity (), LIST_TYPE_FORCE); while (target_force) { if (target_force != force) { target_side = get_local_entity_int_value (target_force, INT_TYPE_SIDE); keysite = get_local_entity_first_child (target_force, LIST_TYPE_KEYSITE_FORCE); while (keysite) { if (get_local_entity_int_value (keysite, INT_TYPE_POTENTIAL_CAMPAIGN_OBJECTIVE)) { if (get_local_entity_int_value (keysite, INT_TYPE_IN_USE)) { float actual_range; vec3d *pos; list [count] = keysite; pos = get_local_entity_vec3d_ptr (keysite, VEC3D_TYPE_POSITION); get_closest_keysite (NUM_ENTITY_SUB_TYPE_KEYSITES, target_side, pos, 1.0 * KILOMETRE, &actual_range, keysite); rating [count] = actual_range; highest = max (highest, rating [count]); count ++; } } keysite = get_local_entity_child_succ (keysite, LIST_TYPE_KEYSITE_FORCE); } } target_force = get_local_entity_child_succ (target_force, LIST_TYPE_FORCE); } // // Normalise ratings // if (highest == 0.0) { debug_fatal ("SETUP: No sector importance for side %s", entity_side_short_names [side]); } for (loop = 0; loop < count; loop ++) { rating [loop] = rating [loop] / highest; } // // obligatory random factor // for (loop = 0; loop < count; loop ++) { rating [loop] += frand1 (); } // // sort the list // quicksort_entity_list (list, count, rating); // // now find the best N targets and link them into the force // count = min (count, NUMBER_OF_CAMPAIGN_OBJECTIVES_PER_SIDE); for (loop = 0; loop < count; loop ++) { insert_local_entity_into_parents_child_list (list [loop], LIST_TYPE_CAMPAIGN_OBJECTIVE, force, NULL); debug_log ("Side %s Objective :- %s (%s)", entity_side_short_names [side], get_local_entity_string (list [loop], STRING_TYPE_KEYSITE_NAME), get_local_entity_string (list [loop], STRING_TYPE_FULL_NAME)); } free_mem (list); free_mem (rating); }
void assess_group_supplies (entity *en) { entity *keysite, *force; group *raw; float required, level; raw = get_local_entity_data (en); if (get_local_entity_int_value (en, INT_TYPE_RESUPPLY_SOURCE) == RESUPPLY_SOURCE_GROUP) { // // Check if Group needs to request Supplies via Mission... // if (raw->supplies.ammo_supply_level < 100.0) { force = get_local_force_entity (get_local_entity_int_value (en, INT_TYPE_SIDE)); #if DEBUG_MODULE || DEBUG_SUPPLY debug_log ("GROUP: SUPPLY_INFO: ground group %s low on ammo, requesting Supply mission", get_local_entity_string (en, STRING_TYPE_FULL_NAME)); #endif notify_local_entity (ENTITY_MESSAGE_FORCE_LOW_ON_SUPPLIES, force, en, ENTITY_SUB_TYPE_CARGO_AMMO); } else if (raw->supplies.fuel_supply_level < 100.0) { force = get_local_force_entity (get_local_entity_int_value (en, INT_TYPE_SIDE)); #if DEBUG_MODULE || DEBUG_SUPPLY debug_log ("GROUP: SUPPLY_INFO: ground group %s low on fuel, requesting Supply mission", get_local_entity_string (en, STRING_TYPE_FULL_NAME)); #endif notify_local_entity (ENTITY_MESSAGE_FORCE_LOW_ON_SUPPLIES, force, en, ENTITY_SUB_TYPE_CARGO_FUEL); } } else if (get_local_entity_int_value (en, INT_TYPE_RESUPPLY_SOURCE) == RESUPPLY_SOURCE_KEYSITE) { // // check all group is landed. If so refuel/rearm group via keysite supplies // if (get_local_entity_int_value (en, INT_TYPE_GROUP_MODE) == GROUP_MODE_IDLE) { if (raw->supplies.ammo_supply_level < 100.0) { // // re-arm // keysite = get_local_entity_parent (en, LIST_TYPE_KEYSITE_GROUP); if ((!keysite) || (get_local_entity_type (keysite) != ENTITY_TYPE_KEYSITE)) { keysite = get_closest_keysite (NUM_ENTITY_SUB_TYPE_KEYSITES, raw->side, get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION), 1.0 * KILOMETRE, NULL, NULL); } ASSERT (keysite); level = get_local_entity_float_value (keysite, FLOAT_TYPE_AMMO_SUPPLY_LEVEL); required = 100.0 - (raw->supplies.ammo_supply_level * AMMO_USAGE_ACCELERATOR); required = bound (required, 0.0, level); level -= required; set_client_server_entity_float_value (keysite, FLOAT_TYPE_AMMO_SUPPLY_LEVEL, level); set_client_server_entity_float_value (en, FLOAT_TYPE_AMMO_SUPPLY_LEVEL, raw->supplies.ammo_supply_level + required); #if DEBUG_MODULE || DEBUG_SUPPLY debug_log ("GROUP: SUPPLY_INFO: Air group %s members landed, rearming group (now ammo = %f, fuel = %f) from keysite %s (%d) (now ammo = %f, fuel = %f)", get_local_entity_string (en, STRING_TYPE_FULL_NAME), get_local_entity_float_value (en, FLOAT_TYPE_AMMO_SUPPLY_LEVEL), get_local_entity_float_value (en, FLOAT_TYPE_FUEL_SUPPLY_LEVEL), get_local_entity_string (keysite, STRING_TYPE_FULL_NAME), get_local_entity_index (keysite), get_local_entity_float_value (keysite, FLOAT_TYPE_AMMO_SUPPLY_LEVEL), get_local_entity_float_value (keysite, FLOAT_TYPE_FUEL_SUPPLY_LEVEL)); #endif } if (raw->supplies.fuel_supply_level < 100.0) { // // re-fuel // keysite = get_local_entity_parent (en, LIST_TYPE_KEYSITE_GROUP); if ((!keysite) || (get_local_entity_type (keysite) != ENTITY_TYPE_KEYSITE)) { keysite = get_closest_keysite (NUM_ENTITY_SUB_TYPE_KEYSITES, raw->side, get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION), 1.0 * KILOMETRE, NULL, NULL); } ASSERT (keysite); level = get_local_entity_float_value (keysite, FLOAT_TYPE_FUEL_SUPPLY_LEVEL); required = 100.0 - (raw->supplies.fuel_supply_level * FUEL_USAGE_ACCELERATOR); required = bound (required, 0.0, level); level -= required; set_client_server_entity_float_value (keysite, FLOAT_TYPE_FUEL_SUPPLY_LEVEL, level); set_client_server_entity_float_value (en, FLOAT_TYPE_FUEL_SUPPLY_LEVEL, raw->supplies.fuel_supply_level + required); #if DEBUG_MODULE || DEBUG_SUPPLY debug_log ("GROUP: SUPPLY_INFO: Air group %s members landed, refuelling group (now ammo = %f, fuel = %f) from keysite %s (%d) (now ammo = %f, fuel = %f)", get_local_entity_string (en, STRING_TYPE_FULL_NAME), get_local_entity_float_value (en, FLOAT_TYPE_AMMO_SUPPLY_LEVEL), get_local_entity_float_value (en, FLOAT_TYPE_FUEL_SUPPLY_LEVEL), get_local_entity_string (keysite, STRING_TYPE_FULL_NAME), get_local_entity_index (keysite), get_local_entity_float_value (keysite, FLOAT_TYPE_AMMO_SUPPLY_LEVEL), get_local_entity_float_value (keysite, FLOAT_TYPE_FUEL_SUPPLY_LEVEL)); #endif } } } }