void respond_to_player_task_assign_request (entity *pilot, entity *task, entity *mobile) { entity *group; ASSERT (pilot); ASSERT (mobile); ASSERT (task); ASSERT (get_comms_model () == COMMS_MODEL_SERVER); group = get_local_entity_parent (mobile, LIST_TYPE_MEMBER); if ((!get_local_entity_first_child (task, LIST_TYPE_GUIDE)) && (!get_local_group_primary_task (group))) { if (assign_primary_task_to_group (group, task)) { transmit_entity_comms_message (ENTITY_COMMS_TASK_ASSIGN_RESULT, pilot, task, mobile); return; } } else { if (get_local_group_primary_task (group)) { transmit_entity_comms_message (ENTITY_COMMS_TASK_ASSIGN_RESULT, pilot, task, mobile); return; } } transmit_entity_comms_message (ENTITY_COMMS_TASK_ASSIGN_RESULT, pilot, NULL, NULL); }
static void kill_local (entity *en) { int losses; entity *task, *group, *keysite, *destroy_task; ship_vehicle *raw; //////////////////////////////////////// // // PRE-AMBLE // //////////////////////////////////////// #if DEBUG_MODULE >= 2 debug_log_entity_args (ENTITY_DEBUG_LOCAL, ENTITY_DEBUG_KILL, en); #endif if (!get_local_entity_int_value (en, INT_TYPE_ALIVE)) { return; } raw = (ship_vehicle *) get_local_entity_data (en); group = get_local_entity_parent (en, LIST_TYPE_MEMBER); ASSERT (group); keysite = NULL; if (tacview_is_logging()) write_tacview_unit_event(en, TACVIEW_UNIT_DESTROYED, NULL); // // update force info // remove_from_force_info (get_local_force_entity ((entity_sides) raw->vh.mob.side), en); //////////////////////////////////////// // // VALIDATE // //////////////////////////////////////// //////////////////////////////////////// // // DESTROY COMPONENTS // //////////////////////////////////////// if (get_comms_model () == COMMS_MODEL_SERVER) { task = get_local_entity_first_child (en, LIST_TYPE_TASK_DEPENDENT); while (task) { destroy_task = task; task = get_local_entity_child_succ (task, LIST_TYPE_TASK_DEPENDENT); if (destroy_task->type == ENTITY_TYPE_TASK) { #if DEBUG_MODULE debug_log ("SH_DSTRY: killing ship, notifying task %s complete", entity_sub_type_task_names [get_local_entity_int_value (destroy_task, INT_TYPE_ENTITY_SUB_TYPE)]); #endif notify_local_entity (ENTITY_MESSAGE_TASK_COMPLETED, destroy_task, en, TASK_TERMINATED_OBJECTIVE_MESSAGE); } } // // Release landing lock (if any) // release_mobile_entity_landing_locks (en); //////////////////////////////////////// // // UNLINK FROM SYSTEM // //////////////////////////////////////// // // Destroy keysite entity if ship is carrier // keysite = get_local_entity_first_child (en, LIST_TYPE_MOVEMENT_DEPENDENT); while (keysite) { if (get_local_entity_type (keysite) == ENTITY_TYPE_KEYSITE) { break; } keysite = get_local_entity_child_succ (keysite, LIST_TYPE_MOVEMENT_DEPENDENT); } } // // ship_vehicle // // // vehicle // unlink_local_entity_children (en, LIST_TYPE_TASK_DEPENDENT); unlink_local_entity_children (en, LIST_TYPE_MOVEMENT_DEPENDENT); delete_local_entity_from_parents_child_list (en, LIST_TYPE_MEMBER); delete_local_entity_from_parents_child_list (en, LIST_TYPE_MOVEMENT_DEPENDENT); delete_local_entity_from_parents_child_list (en, LIST_TYPE_FOLLOWER); // gunship_target_link // member_link // view_link delete_local_entity_from_parents_child_list (en, LIST_TYPE_TAKEOFF_QUEUE); // // mobile // // // kill weapon sound effects // kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_CHAIN_GUN); // // kill engine sound effects // kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING1); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING2); unlink_local_entity_children (en, LIST_TYPE_TARGET); delete_local_entity_from_parents_child_list (en, LIST_TYPE_PADLOCK); // sector_link delete_local_entity_from_parents_child_list (en, LIST_TYPE_TARGET); // update_link set_local_entity_int_value (en, INT_TYPE_OPERATIONAL_STATE, OPERATIONAL_STATE_STOPPED); //////////////////////////////////////// // // KILL // //////////////////////////////////////// // must be done before alive flag set remove_mobile_values_from_sector (get_local_entity_parent (en, LIST_TYPE_SECTOR), en); set_local_entity_int_value (en, INT_TYPE_ALIVE, FALSE); damage_ship_3d_object (en); // // group losses // losses = get_local_entity_int_value (group, INT_TYPE_LOSSES); losses ++; set_local_entity_int_value (group, INT_TYPE_LOSSES, losses); // // task losses // task = get_local_group_primary_task (group); if (task) { losses = get_local_entity_int_value (task, INT_TYPE_LOSSES); losses ++; set_local_entity_int_value (task, INT_TYPE_LOSSES, losses); } // // Notify Campaign Screen // notify_campaign_screen (CAMPAIGN_SCREEN_GROUP_REMOVE_MEMBER, group); if (get_comms_model () == COMMS_MODEL_SERVER) { // // Notify the GROUP that the mobile has been killed (N.B. must be done AFTER mobile is unlinked from member list) // notify_local_entity (ENTITY_MESSAGE_MOBILE_KILLED, group, en); // // Kill the keysite if ship is the carrier (N.B. must be done AFTER ships alive flag cleared) // if (keysite) { kill_client_server_entity (keysite); } } //////////////////////////////////////// // // SPECIAL EFFECTS // //////////////////////////////////////// if (get_comms_model () == COMMS_MODEL_SERVER) { create_client_server_object_killed_explosion_effect (en); } #if LANDING_ROUTE_CHECK destroy_debug_entity_landing_route_check (en); #endif ///////////////////////////////////////////////////////////////// // // SPECIAL_EFFECT_HOOK FOR BEING_DESTROYED // ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// }
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; } }
static void kill_local (entity *en) { int losses; routed_vehicle *raw; entity *task, *destroy_task, *group; //////////////////////////////////////// // // PRE-AMBLE // //////////////////////////////////////// #if DEBUG_MODULE >= 2 debug_log_entity_args (ENTITY_DEBUG_LOCAL, ENTITY_DEBUG_KILL, en); #endif if (!get_local_entity_int_value (en, INT_TYPE_ALIVE)) { return; } raw = get_local_entity_data (en); group = get_local_entity_parent (en, LIST_TYPE_MEMBER); ASSERT (group); // // update force info // remove_from_force_info (get_local_force_entity (raw->vh.mob.side), en); //////////////////////////////////////// // // VALIDATE // //////////////////////////////////////// //////////////////////////////////////// // // DESTROY COMPONENTS // //////////////////////////////////////// if (get_comms_model () == COMMS_MODEL_SERVER) { //////////////////////////////////////// // // SEND NOTIFY MESSAGES // //////////////////////////////////////// // notify regen of kill add_entity_to_regen_queue ( get_local_entity_int_value(en, INT_TYPE_SIDE), get_local_entity_type(en), get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE), get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE) ); // // // task = get_local_entity_first_child (en, LIST_TYPE_TASK_DEPENDENT); while (task) { destroy_task = task; task = get_local_entity_child_succ (task, LIST_TYPE_TASK_DEPENDENT); if (get_local_entity_type (destroy_task) == ENTITY_TYPE_TASK) { #if DEBUG_MODULE debug_log ("RV_DSTRY: killing routed vehicle, notifying task %s complete", entity_sub_type_task_names [get_local_entity_int_value (destroy_task, INT_TYPE_ENTITY_SUB_TYPE)]); #endif notify_local_entity (ENTITY_MESSAGE_TASK_COMPLETED, destroy_task, en, TASK_TERMINATED_OBJECTIVE_MESSAGE); } } // // Release landing lock (if any) // release_mobile_entity_landing_locks (en); } //////////////////////////////////////// // // UNLINK FROM SYSTEM // //////////////////////////////////////// // // routed_vehicle // // // vehicle // unlink_local_entity_children (en, LIST_TYPE_TASK_DEPENDENT); unlink_local_entity_children (en, LIST_TYPE_MOVEMENT_DEPENDENT); #if DEBUG_MODULE debug_log ("RV_DSTRY: removing member %d from group %d", get_local_entity_index (en), get_local_entity_index (raw->vh.member_link.parent)); #endif delete_local_entity_from_parents_child_list (en, LIST_TYPE_MEMBER); delete_local_entity_from_parents_child_list (en, LIST_TYPE_MOVEMENT_DEPENDENT); delete_local_entity_from_parents_child_list (en, LIST_TYPE_FOLLOWER); // gunship_target_link // member_link // view_link delete_local_entity_from_parents_child_list (en, LIST_TYPE_TAKEOFF_QUEUE); // // mobile // // // kill weapon sound effects // kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_CHAIN_GUN); // // kill engine sound effects // kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING1); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING2); unlink_local_entity_children (en, LIST_TYPE_TARGET); delete_local_entity_from_parents_child_list (en, LIST_TYPE_PADLOCK); // sector_link delete_local_entity_from_parents_child_list (en, LIST_TYPE_TARGET); // update_link set_local_entity_int_value (en, INT_TYPE_OPERATIONAL_STATE, OPERATIONAL_STATE_DYING); //////////////////////////////////////// // // KILL // //////////////////////////////////////// // must be done before alive flag set to FALSE remove_mobile_values_from_sector (get_local_entity_parent (en, LIST_TYPE_SECTOR), en); set_local_entity_int_value (en, INT_TYPE_ALIVE, FALSE); damage_routed_vehicle_3d_object (en); // // group losses // losses = get_local_entity_int_value (group, INT_TYPE_LOSSES); losses ++; set_local_entity_int_value (group, INT_TYPE_LOSSES, losses); // // task losses // task = get_local_group_primary_task (group); if (task) { losses = get_local_entity_int_value (task, INT_TYPE_LOSSES); losses ++; set_local_entity_int_value (task, INT_TYPE_LOSSES, losses); } // // Notify Campaign Screen // notify_campaign_screen (CAMPAIGN_SCREEN_GROUP_REMOVE_MEMBER, group); // // Notify the GROUP that the mobile has been killed (N.B. must be done AFTER mobile is unlinked from member list) // if (get_comms_model () == COMMS_MODEL_SERVER) { notify_local_entity (ENTITY_MESSAGE_MOBILE_KILLED, group, en); } //////////////////////////////////////// // // SPECIAL EFFECTS // //////////////////////////////////////// set_local_entity_float_value (en, FLOAT_TYPE_DEATH_TIMER, calculate_mobile_death_timer_value (en)); routed_vehicle_impact_movement (en); if (get_comms_model () == COMMS_MODEL_SERVER) { create_client_server_object_killed_explosion_effect (en); } #if LANDING_ROUTE_CHECK destroy_debug_entity_landing_route_check (en); #endif ///////////////////////////////////////////////////////////////// // // SPECIAL_EFFECT_HOOK FOR BEING_DESTROYED // //////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// }
int assign_task_to_group (entity *group, entity *task_en, unsigned int valid_members) { int sites_required; entity_sub_types sub_type, group_type; entity *force, *landing, *end_keysite, *start_keysite, *guide, *member; vec3d *pos; task *task_raw; debug_assert (get_comms_model () == COMMS_MODEL_SERVER); ASSERT (task_en); ASSERT (group); ASSERT (!(get_local_group_primary_task (group) && (get_local_entity_int_value (task_en, INT_TYPE_PRIMARY_TASK)))); task_raw = ( task * ) get_local_entity_data (task_en); group_type = get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE); member = get_local_entity_first_child (group, LIST_TYPE_MEMBER); // don't if no members or if the group is a CARRIER if (!member) { return FALSE; } if (get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_GROUP_ASSAULT_SHIP) { if (task_raw->sub_type != ENTITY_SUB_TYPE_TASK_ENGAGE) { return FALSE; } } // // check for invalid tasks // switch (task_raw->sub_type) { case ENTITY_SUB_TYPE_TASK_LANDING: case ENTITY_SUB_TYPE_TASK_LANDING_HOLDING: case ENTITY_SUB_TYPE_TASK_TAKEOFF: case ENTITY_SUB_TYPE_TASK_TAKEOFF_HOLDING: { #ifdef DEBUG debug_fatal ("ASSIGN: Invalid task type (%s) for assign_task_to_group", get_local_entity_string (task_en, STRING_TYPE_FULL_NAME)); #endif return FALSE; } } // // Create route // if (get_local_entity_int_value (group, INT_TYPE_GROUP_LIST_TYPE) == LIST_TYPE_KEYSITE_GROUP) { start_keysite = get_local_entity_parent (group, LIST_TYPE_KEYSITE_GROUP); } else { // start_keysite = get_closest_keysite (NUM_ENTITY_SUB_TYPE_KEYSITES, task_raw->side, get_local_entity_vec3d_ptr (group, VEC3D_TYPE_POSITION), 1.0 * KILOMETRE, NULL); start_keysite = NULL; } pos = get_local_entity_vec3d_ptr (task_en, VEC3D_TYPE_STOP_POSITION); force = get_local_force_entity ( ( entity_sides ) get_local_entity_int_value (task_en, INT_TYPE_SIDE) ); sub_type = group_database [group_type].default_landing_type; landing = NULL; end_keysite = NULL; if (get_local_entity_int_value (task_en, INT_TYPE_ASSESS_LANDING)) { ASSERT (start_keysite); end_keysite = ( entity * ) get_local_entity_ptr_value (task_en, PTR_TYPE_RETURN_KEYSITE); if (end_keysite) { // // check end keysite has suitble free landing sites // if (start_keysite != end_keysite) { // // if end keysite == start keysite then keysite MUST have enough sites because the aircraft are already there // sites_required = get_local_group_member_count (group); if (get_keysite_landing_sites_available (end_keysite, sub_type) < sites_required) { // // END keysite was specified - but no free landing sites for this group // return FALSE; } } } else { // // No END keysite specified so return to start keysite // end_keysite = start_keysite; set_local_entity_ptr_value (task_en, PTR_TYPE_RETURN_KEYSITE, end_keysite); } ASSERT (end_keysite); landing = get_local_entity_landing_entity (end_keysite, group_database [get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE)].default_landing_type); } if (create_generic_waypoint_route (group, task_en, end_keysite, NULL, NULL, NULL, 0)) { #if DEBUG_MODULE debug_log ("ASSIGN: group %s (%d) assigned to task %s (%d)", get_local_entity_string (group, STRING_TYPE_FULL_NAME), get_local_entity_index (group), get_local_entity_string (task_en, STRING_TYPE_FULL_NAME), get_local_entity_index (task_en)); #endif // // Assign task // guide = push_task_onto_group_task_stack (group, task_en, valid_members); assign_task_to_group_members (group, guide, valid_members); return TRUE; } 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; }
static void kill_local (entity *en) { int losses; entity *task, *group, *destroy_task; fixed_wing *raw; //////////////////////////////////////// // // PRE-AMBLE // //////////////////////////////////////// #if DEBUG_MODULE >= 2 debug_log_entity_args (ENTITY_DEBUG_LOCAL, ENTITY_DEBUG_KILL, en); #endif if (!get_local_entity_int_value (en, INT_TYPE_ALIVE)) { return; } raw = (fixed_wing *) get_local_entity_data (en); group = get_local_entity_parent (en, LIST_TYPE_MEMBER); ASSERT (group); // // update force info // remove_from_force_info (get_local_force_entity ((entity_sides) raw->ac.mob.side), en); if (tacview_is_logging()) write_tacview_unit_event(en, TACVIEW_UNIT_DESTROYED, NULL); //////////////////////////////////////// // // VALIDATE // //////////////////////////////////////// //////////////////////////////////////// // // SEND NOTIFY MESSAGES // //////////////////////////////////////// if (get_comms_model () == COMMS_MODEL_SERVER) { // notify regen of kill add_entity_to_regen_queue ( (entity_sides) get_local_entity_int_value(en, INT_TYPE_SIDE), get_local_entity_type(en), get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE), get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE) ); task = get_local_entity_first_child (en, LIST_TYPE_TASK_DEPENDENT); while (task) { destroy_task = task; task = get_local_entity_child_succ (task, LIST_TYPE_TASK_DEPENDENT); if (destroy_task->type == ENTITY_TYPE_TASK) { #if DEBUG_MODULE debug_log ("FW_DSTRY: killing fixed wing, notifying task %s complete", entity_sub_type_task_names [get_local_entity_int_value (destroy_task, INT_TYPE_ENTITY_SUB_TYPE)]); #endif notify_local_entity (ENTITY_MESSAGE_TASK_COMPLETED, destroy_task, en, TASK_TERMINATED_OBJECTIVE_MESSAGE); } } // // Release landing lock (if any) // release_mobile_entity_landing_locks (en); } //////////////////////////////////////// // // UNLINK FROM SYSTEM // //////////////////////////////////////// // // fixed_wing // // // aircraft // // aircrew_root unlink_local_entity_children (en, LIST_TYPE_TASK_DEPENDENT); // unlink_local_entity_children (en, LIST_TYPE_LAUNCHED_WEAPON); delete_local_entity_from_parents_child_list (en, LIST_TYPE_FOLLOWER); delete_local_entity_from_parents_child_list (en, LIST_TYPE_MEMBER); // gunship_target_link // member_link // view_link delete_local_entity_from_parents_child_list (en, LIST_TYPE_TAKEOFF_QUEUE); // // mobile // // // kill weapon sound effects // kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_CHAIN_GUN); // // kill engine sound effects // kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING1); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING2); // // Kill speech // notify_speech_buffers_entity_killed (en); // special_effect root unlink_local_entity_children (en, LIST_TYPE_TARGET); delete_local_entity_from_parents_child_list (en, LIST_TYPE_PADLOCK); // sector_link delete_local_entity_from_parents_child_list (en, LIST_TYPE_TARGET); // update_link set_local_entity_int_value (en, INT_TYPE_OPERATIONAL_STATE, OPERATIONAL_STATE_DYING); // // death timer (set time after which entity is totally destroyed) // set_local_entity_float_value (en, FLOAT_TYPE_DEATH_TIMER, calculate_mobile_death_timer_value (en)); //////////////////////////////////////// // // KILL // //////////////////////////////////////// damage_fixed_wing_3d_object (en); // must be done before alive flag set to FALSE remove_mobile_values_from_sector (get_local_entity_parent (en, LIST_TYPE_SECTOR), en); set_local_entity_int_value (en, INT_TYPE_ALIVE, FALSE); // // group losses // losses = get_local_entity_int_value (group, INT_TYPE_LOSSES); losses ++; set_local_entity_int_value (group, INT_TYPE_LOSSES, losses); // // task losses // task = get_local_group_primary_task (group); if (task) { losses = get_local_entity_int_value (task, INT_TYPE_LOSSES); losses ++; set_local_entity_int_value (task, INT_TYPE_LOSSES, losses); } // // Notify Campaign Screen // notify_campaign_screen (CAMPAIGN_SCREEN_GROUP_REMOVE_MEMBER, group); // // Notify the GROUP that the mobile has been killed (N.B. must be done AFTER mobile is unlinked from member list) // if (get_comms_model () == COMMS_MODEL_SERVER) { notify_local_entity (ENTITY_MESSAGE_MOBILE_KILLED, group, en); } //////////////////////////////////////// // // SPECIAL EFFECTS // //////////////////////////////////////// set_local_fixed_wing_afterburner_state (en, OFF); fixed_wing_impact_movement (en); if (get_comms_model () == COMMS_MODEL_SERVER) { vec3d *position; sound_sample_indices sound_sample_index; create_client_server_object_killed_explosion_effect (en); position = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); sound_sample_index = SOUND_SAMPLE_INDEX_SHOT_DOWN_AIRCRAFT; create_client_server_sound_effect_entity ( en, ENTITY_SIDE_NEUTRAL, ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING1, SOUND_CHANNEL_SOUND_EFFECT, SOUND_LOCALITY_ALL, NULL, // position 1.0, // amplification 1.0, // Werewolf pitch TRUE, // valid sound effect TRUE, // looping 1, // sample count &sound_sample_index // sample index list ); } #if LANDING_ROUTE_CHECK destroy_debug_entity_landing_route_check (en); #endif ///////////////////////////////////////////////////////////////// // // SPECIAL_EFFECT_HOOK FOR BEING_DESTROYED // ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// }
static void kill_local (entity *en) { int losses; helicopter *raw; entity *task, *group, *member, *destroy_task; //////////////////////////////////////// // // PRE-AMBLE // //////////////////////////////////////// #if DEBUG_MODULE >= 2 debug_log_entity_args (ENTITY_DEBUG_LOCAL, ENTITY_DEBUG_KILL, en); #endif if (!get_local_entity_int_value (en, INT_TYPE_ALIVE)) { return; } raw = get_local_entity_data (en); group = get_local_entity_parent (en, LIST_TYPE_MEMBER); ASSERT (group); // // update force info // remove_from_force_info (get_local_force_entity (raw->ac.mob.side), en); if (en == get_gunship_entity ()) { // // Award Points for mission // task = get_local_entity_primary_task (en); if (task) { if (get_local_entity_int_value (task, INT_TYPE_TASK_STATE) == TASK_STATE_COMPLETED) { // // Only award points for COMPLETE missions (also means player can't rejoin that mission and get points again) // notify_gunship_entity_mission_terminated (en, task); } } } //////////////////////////////////////// // // VALIDATE // //////////////////////////////////////// //////////////////////////////////////// // // DESTROY COMPONENTS // //////////////////////////////////////// #if DEBUG_MODULE debug_log ("HC_DSTRY: killing helicopter %s", entity_sub_type_aircraft_names [raw->ac.mob.sub_type]); #endif if (get_comms_model () == COMMS_MODEL_SERVER) { // notify regen of kill add_entity_to_regen_queue ( get_local_entity_int_value(en, INT_TYPE_SIDE), get_local_entity_type(en), get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE), get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE) ); // // notify task dependents // task = get_local_entity_first_child (en, LIST_TYPE_TASK_DEPENDENT); while (task) { destroy_task = task; task = get_local_entity_child_succ (task, LIST_TYPE_TASK_DEPENDENT); if (destroy_task->type == ENTITY_TYPE_TASK) { #if DEBUG_MODULE debug_log ("HC_DSTRY: killing helicopter, notifying task %s complete", entity_sub_type_task_names [get_local_entity_int_value (destroy_task, INT_TYPE_ENTITY_SUB_TYPE)]); #endif notify_local_entity (ENTITY_MESSAGE_TASK_COMPLETED, destroy_task, en, TASK_TERMINATED_OBJECTIVE_MESSAGE); } } // // Release landing lock (if any) // release_mobile_entity_landing_locks (en); // // if group contains player, set all helicopters in group to "weapons free", and clear "hold position" flag // if (get_local_entity_int_value (en, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI) { member = get_local_entity_first_child (group, LIST_TYPE_MEMBER); while (member) { set_client_server_entity_int_value (member, INT_TYPE_WEAPONS_HOLD, FALSE); set_client_server_entity_int_value (member, INT_TYPE_POSITION_HOLD, FALSE); member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER); } } } //////////////////////////////////////// // // UNLINK FROM SYSTEM // //////////////////////////////////////// // // helicopter // unlink_local_entity_children (en, LIST_TYPE_GUNSHIP_TARGET); unlink_local_entity_children (en, LIST_TYPE_PADLOCK); // // aircraft // // aircrew_root unlink_local_entity_children (en, LIST_TYPE_TASK_DEPENDENT); //////////////////////////////////////// // // the eject sequence relies on launched weapons NOT being unlinked // // unlink_local_entity_children (en, LIST_TYPE_LAUNCHED_WEAPON); // //////////////////////////////////////// delete_local_entity_from_parents_child_list (en, LIST_TYPE_FOLLOWER); delete_local_entity_from_parents_child_list (en, LIST_TYPE_MEMBER); // gunship_target_link // member_link delete_local_entity_from_parents_child_list (en, LIST_TYPE_MOVEMENT_DEPENDENT); // view_link delete_local_entity_from_parents_child_list (en, LIST_TYPE_TAKEOFF_QUEUE); // // mobile // // // kill weapon sound effects // kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_CHAIN_GUN); // // kill engine sound effects // kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_ROTOR_LOOPING); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_ROTOR_WIND_UP); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_ROTOR_WIND_DOWN); // // kill radio / warning effects // kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_INCOMING_MISSILE_WARNING); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_LOCK_ON_TONE); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_MCA); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_RADAR_LOCKED); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_RADAR_TRACKED); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_CPG_MESSAGE); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_RADIO_MESSAGE); kill_local_entity_sound_type (en, ENTITY_SUB_TYPE_EFFECT_SOUND_WARNING_MESSAGE); notify_speech_buffers_entity_killed (en); unlink_local_entity_children (en, LIST_TYPE_TARGET); delete_local_entity_from_parents_child_list (en, LIST_TYPE_PADLOCK); // sector_link delete_local_entity_from_parents_child_list (en, LIST_TYPE_TARGET); // update_link // // death timer (set time after which entity is totally destroyed) // set_local_entity_float_value (en, FLOAT_TYPE_DEATH_TIMER, calculate_mobile_death_timer_value (en)); //////////////////////////////////////// // // KILL // //////////////////////////////////////// damage_helicopter_3d_object (en); // must be done before alive flag set to FALSE remove_mobile_values_from_sector (get_local_entity_parent (en, LIST_TYPE_SECTOR), en); set_local_entity_int_value (en, INT_TYPE_ALIVE, FALSE); // // group losses // losses = get_local_entity_int_value (group, INT_TYPE_LOSSES); losses ++; set_local_entity_int_value (group, INT_TYPE_LOSSES, losses); // // task losses // task = get_local_group_primary_task (group); if (task) { losses = get_local_entity_int_value (task, INT_TYPE_LOSSES); losses ++; set_local_entity_int_value (task, INT_TYPE_LOSSES, losses); } // // Notify Campaign Screen // notify_campaign_screen (CAMPAIGN_SCREEN_GROUP_REMOVE_MEMBER, group); // // Notify the GROUP that the mobile has been killed (N.B. must be done AFTER mobile is unlinked from member list) // if (get_comms_model () == COMMS_MODEL_SERVER) { notify_local_entity (ENTITY_MESSAGE_MOBILE_KILLED, group, en); } // // Notify force to check campaign criteria // if (get_comms_model () == COMMS_MODEL_SERVER) { entity *force; force = get_local_entity_first_child (get_session_entity (), LIST_TYPE_FORCE); while (force) { notify_local_entity (ENTITY_MESSAGE_CHECK_CAMPAIGN_OBJECTIVES, force, en); force = get_local_entity_child_succ (force, LIST_TYPE_FORCE); } } //////////////////////////////////////// // // SPECIAL EFFECTS // //////////////////////////////////////// helicopter_impact_movement (en); if (get_comms_model () == COMMS_MODEL_SERVER) { vec3d *position; sound_sample_indices sound_sample_index; set_client_server_entity_int_value (en, INT_TYPE_MAIN_ROTOR_DAMAGED, TRUE); set_client_server_entity_int_value (en, INT_TYPE_TAIL_ROTOR_DAMAGED, TRUE); create_client_server_object_killed_explosion_effect (en); position = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); sound_sample_index = SOUND_SAMPLE_INDEX_SHOT_DOWN_HELICOPTER; create_client_server_sound_effect_entity ( en, ENTITY_SIDE_NEUTRAL, ENTITY_SUB_TYPE_EFFECT_SOUND_ROTOR_LOOPING, SOUND_CHANNEL_SOUND_EFFECT, SOUND_LOCALITY_ALL, NULL, // position 1.0, // amplification TRUE, // valid sound effect TRUE, // looping 1, // sample count &sound_sample_index // sample index list ); } set_local_entity_int_value (en, INT_TYPE_OPERATIONAL_STATE, OPERATIONAL_STATE_DYING); //////////////////////////////////////// // // VIEWS // //////////////////////////////////////// if ((en == get_gunship_entity ()) && (!get_local_entity_int_value (en, INT_TYPE_EJECTED))) { set_gunship_entity (NULL); } #if LANDING_ROUTE_CHECK destroy_debug_entity_landing_route_check (en); #endif ///////////////////////////////////////////////////////////////// // // SPECIAL_EFFECT_HOOK FOR BEING_DESTROYED // ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// }
void stop_vehicles_on_route (int start_node, int end_node) { entity *task, *force, *group, *member; int index1, index2; ASSERT (get_comms_model () == COMMS_MODEL_SERVER); force = get_local_entity_first_child (get_session_entity (), LIST_TYPE_FORCE); while (force) { group = get_local_entity_first_child (force, LIST_TYPE_GROUND_REGISTRY); while (group) { task = get_local_group_primary_task (group); if (task) { member = (entity *) get_local_entity_ptr_value (group, PTR_TYPE_GROUP_LEADER); ASSERT (member); index1 = get_local_entity_int_value (member, INT_TYPE_WAYPOINT_THIS_INDEX); index2 = get_local_entity_int_value (member, INT_TYPE_WAYPOINT_NEXT_INDEX); if (((index1 == start_node) && (index2 == end_node)) || ((index2 == start_node) && (index1 == end_node))) { // // destroy task // notify_local_entity (ENTITY_MESSAGE_TASK_TERMINATED, task, group, TASK_TERMINATED_GROUP_DESTROYED); // // set group to busy, and operational state to stopped // set_client_server_entity_int_value (group, INT_TYPE_GROUP_MODE, GROUP_MODE_BUSY); { entity *mb; mb = get_local_entity_first_child (group, LIST_TYPE_MEMBER); while (mb) { set_client_server_entity_int_value (mb, INT_TYPE_OPERATIONAL_STATE, OPERATIONAL_STATE_STOPPED); mb = get_local_entity_child_succ (mb, LIST_TYPE_MEMBER); } } ///////////////////////////////////////////////////////////////// // // SPECIAL_EFFECT_HOOK FOR BRIDGE OUT // ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// } } group = get_local_entity_child_succ (group, LIST_TYPE_GROUND_REGISTRY); } force = get_local_entity_child_succ (force, LIST_TYPE_FORCE); } }