int clear_ship_fires (entity *ship_en, entity_sub_types type) { entity *en; vec3d *pos; en = get_local_entity_first_child (ship_en, LIST_TYPE_SPECIAL_EFFECT); while (en) { if (en->type == ENTITY_TYPE_SMOKE_LIST) { if (get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE) == type) { pos = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); if (pos->y < 0.0) { set_local_entity_float_value (en, FLOAT_TYPE_GENERATOR_LIFETIME, 0.0); } } } en = get_local_entity_child_succ (en, LIST_TYPE_SPECIAL_EFFECT); } return TRUE; }
static int response_to_unlink_parent (entity_messages message, entity *receiver, entity *sender, va_list pargs) { list_types list_type; #if DEBUG_MODULE debug_log_entity_message (message, receiver, sender, pargs); #endif list_type = va_arg (pargs, list_types); if (list_type == LIST_TYPE_SPECIAL_EFFECT) { // // set the effect_lifetime so that it will be destroyed next update // set_local_entity_float_value (receiver, FLOAT_TYPE_EFFECT_LIFETIME, get_local_entity_float_value (receiver, FLOAT_TYPE_SPRITE_LIFETIME)); } return (TRUE); }
static int response_to_unlink_parent (entity_messages message, entity *receiver, entity *sender, va_list pargs) { list_types list_type; #if DEBUG_MODULE debug_log_entity_message (message, receiver, sender, pargs); #endif list_type = va_arg (pargs, list_types); switch (list_type) { //////////////////////////////////////// case LIST_TYPE_GUNSHIP_TARGET: //////////////////////////////////////// { set_local_entity_int_value (receiver, INT_TYPE_GUNSHIP_RADAR_LOS_CLEAR, FALSE); set_local_entity_float_value (receiver, FLOAT_TYPE_AIR_RADAR_CONTACT_TIMEOUT, AIR_RADAR_CONTACT_TIMEOUT_INVALID); break; } //////////////////////////////////////// case LIST_TYPE_UPDATE: //////////////////////////////////////// { set_local_entity_float_value (receiver, FLOAT_TYPE_VIEW_INTEREST_LEVEL, 0.0); break; } } return (TRUE); }
void update_local_entity_view_interest_level (entity *en) { float level; ASSERT (en); level = get_local_entity_float_value (en, FLOAT_TYPE_VIEW_INTEREST_LEVEL); if (level > 0.0) { level -= get_delta_time (); if (level < 0.0) { level = 0.0; } set_local_entity_float_value (en, FLOAT_TYPE_VIEW_INTEREST_LEVEL, level); } }
void pause_local_continuous_weapon_sound_effect (entity *en, entity_sub_types weapon_sub_type) { entity_sub_types effect_sub_type; ASSERT (en); // // reset burst timer so that it can fire next time round // if (get_comms_model () == COMMS_MODEL_SERVER) { set_local_entity_float_value (en, FLOAT_TYPE_WEAPON_BURST_TIMER, 0.0); } effect_sub_type = weapon_database [weapon_sub_type].launch_sound_effect_sub_type; if (effect_sub_type != ENTITY_SUB_TYPE_EFFECT_SOUND_MISC) { pause_local_entity_sound_type (en, effect_sub_type, 0.5); } }
void update_session_sound_effects (entity *en) { session *raw; entity *spec; vec3d *camera_pos; weathermodes current_weather_mode, target_weather_mode; float alt, trans, value, light_wind_sound_level, heavy_wind_sound_level, rain_sound_levels [WEATHERMODE_LAST]; ASSERT (en); raw = (session *) get_local_entity_data (en); if (in_cockpit) { camera_pos = get_local_entity_vec3d_ptr (get_gunship_entity (), VEC3D_TYPE_POSITION); alt = get_local_entity_float_value (get_gunship_entity (), FLOAT_TYPE_RADAR_ALTITUDE); } else { camera_pos = get_local_entity_vec3d_ptr (get_camera_entity (), VEC3D_TYPE_POSITION); alt = get_local_entity_float_value (get_camera_entity (), FLOAT_TYPE_RADAR_ALTITUDE); } // // rain // memset (rain_sound_levels, 0, sizeof (float) * WEATHERMODE_LAST); if (camera_pos->y < get_cloud_3d_base_height ()) { if ((!in_cockpit) && (alt >= SESSION_RAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE)) { // // rain should only make a sound when it hits either the cockpit, or the ground // } else { get_session_weather_at_point (camera_pos, ¤t_weather_mode, &target_weather_mode, &trans); if (target_weather_mode == current_weather_mode) { rain_sound_levels [target_weather_mode] = 1.0; rain_sound_levels [current_weather_mode] = 1.0; } else { rain_sound_levels [target_weather_mode] = trans; rain_sound_levels [current_weather_mode] = (1.0 - trans); } if (!in_cockpit) { rain_sound_levels [target_weather_mode] *= (1.0 - (alt / SESSION_RAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE)); rain_sound_levels [current_weather_mode] *= (1.0 - (alt / SESSION_RAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE)); } } } // // wind // { float r, wind_speed; wind_speed = get_session_wind_velocity_at_point (camera_pos, NULL); if (wind_speed <= raw->wind_minimum_speed) { r = 0.0; } else if (wind_speed >= raw->wind_maximum_speed) { r = 1.0; } else { r = (wind_speed - raw->wind_minimum_speed) / (raw->wind_maximum_speed - raw->wind_minimum_speed); } ASSERT ((r >= 0.0) && (r <= 1.0)); if (r == 0.0) { light_wind_sound_level = 0.0; heavy_wind_sound_level = 0.0; } else if (r < 0.5) { light_wind_sound_level = r * 2.0; heavy_wind_sound_level = 0.0; } else { light_wind_sound_level = 1.0 - ((r - 0.5) * 2.0); heavy_wind_sound_level = (r - 0.5) * 2.0; } } // // terrain // { float xpos, zpos; xpos = bound (camera_pos->x, MIN_MAP_X, MAX_MAP_X); zpos = bound (camera_pos->z, MIN_MAP_Z, MAX_MAP_Z); get_terrain_3d_types_in_sector (xpos, zpos); } // // set new values // spec = get_local_entity_first_child (en, LIST_TYPE_SPECIAL_EFFECT); while (spec) { switch (get_local_entity_int_value (spec, INT_TYPE_ENTITY_SUB_TYPE)) { case ENTITY_SUB_TYPE_EFFECT_SOUND_AMBIENT_LIGHT_RAIN: { set_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION, rain_sound_levels [WEATHERMODE_LIGHT_RAIN]); break; } case ENTITY_SUB_TYPE_EFFECT_SOUND_AMBIENT_HEAVY_RAIN: { set_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION, rain_sound_levels [WEATHERMODE_HEAVY_RAIN]); break; } case ENTITY_SUB_TYPE_EFFECT_SOUND_AMBIENT_LIGHT_WIND: { set_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION, light_wind_sound_level); break; } case ENTITY_SUB_TYPE_EFFECT_SOUND_AMBIENT_HEAVY_WIND: { set_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION, heavy_wind_sound_level); break; } case ENTITY_SUB_TYPE_EFFECT_SOUND_AMBIENT_SEA: { if (alt >= SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE) { value = 0.0; } else { value = get_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION); if (terrain_types_in_sector [TERRAIN_TYPE_SEA]) { value += (0.5 * get_delta_time ()); } else { value -= (0.5 * get_delta_time ()); } value = bound (value, 0.0, 0.3); value *= bound(1.0 - (alt / SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE), 0.0, 1.0); if (in_cockpit) { value *= 0.75; } } set_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION, value); break; } case ENTITY_SUB_TYPE_EFFECT_SOUND_AMBIENT_JUNGLE: { if (alt >= SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE) { value = 0.0; } else { value = get_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION); if (terrain_types_in_sector [TERRAIN_TYPE_FOREST_TOP]) { value += (0.5 * get_delta_time ()); } else { value -= (0.5 * get_delta_time ()); } value = bound (value, 0.0, 0.3); value *= bound(1.0 - (alt / SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE), 0.0, 1.0); if (in_cockpit) { value *= 0.75; } } set_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION, value); break; } case ENTITY_SUB_TYPE_EFFECT_SOUND_AMB1: { if (alt >= SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE) { value = 0.0; } else { value = get_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION); if (terrain_types_in_sector [TERRAIN_TYPE_RIVER]) { value += (0.5 * get_delta_time ()); } else { value -= (0.5 * get_delta_time ()); } value = bound (value, 0.0, 0.3); value *= bound(1.0 - (alt / SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE), 0.0, 1.0); if (in_cockpit) { value *= 0.75; } } set_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION, value); break; } case ENTITY_SUB_TYPE_EFFECT_SOUND_AMB2: { if (alt >= SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE) { value = 0.0; } else { value = get_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION); if (terrain_types_in_sector [TERRAIN_TYPE_RESERVOIR]) { value += (0.5 * get_delta_time ()); } else { value -= (0.5 * get_delta_time ()); } value = bound (value, 0.0, 0.3); value *= bound(1.0 - (alt / SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE), 0.0, 1.0); if (in_cockpit) { value *= 0.75; } } set_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION, value); break; } case ENTITY_SUB_TYPE_EFFECT_SOUND_AMB3: { if (alt >= SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE) { value = 0.0; } else { value = get_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION); if (terrain_types_in_sector [TERRAIN_TYPE_ALTERED_LAND1]) { value += (0.5 * get_delta_time ()); } else { value -= (0.5 * get_delta_time ()); } value = bound (value, 0.0, 0.3); value *= bound(1.0 - (alt / SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE), 0.0, 1.0); if (in_cockpit) { value *= 0.75; } } set_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION, value); break; } case ENTITY_SUB_TYPE_EFFECT_SOUND_AMB4: { if (alt >= SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE) { value = 0.0; } else { value = get_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION); if (terrain_types_in_sector [TERRAIN_TYPE_ALTERED_LAND2]) { value += (0.5 * get_delta_time ()); } else { value -= (0.5 * get_delta_time ()); } value = bound (value, 0.0, 0.3); value *= bound(1.0 - (alt / SESSION_TERRAIN_SOUND_EFFECT_ZERO_VOLUME_ALTITUDE), 0.0, 1.0); if (in_cockpit) { value *= 0.75; } } set_local_entity_float_value (spec, FLOAT_TYPE_AMPLIFICATION, value); break; } } spec = get_local_entity_child_succ (spec, LIST_TYPE_SPECIAL_EFFECT); } }
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 // //////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// }
static int response_to_link_parent (entity_messages message, entity *receiver, entity *sender, va_list pargs) { list_types list_type; #if DEBUG_MODULE debug_log_entity_message (message, receiver, sender, pargs); #endif list_type = va_arg (pargs, list_types); switch (list_type) { //////////////////////////////////////// case LIST_TYPE_GUNSHIP_TARGET: //////////////////////////////////////// { set_local_entity_int_value (receiver, INT_TYPE_GUNSHIP_RADAR_LOS_CLEAR, TRUE); set_local_entity_float_value (receiver, FLOAT_TYPE_AIR_RADAR_CONTACT_TIMEOUT, AIR_RADAR_CONTACT_TIMEOUT); // show icon on map if gunship scans it. /* if (get_local_entity_int_value (receiver, INT_TYPE_SIDE) == get_global_gunship_side ()) { set_planner_icon_update (receiver, FALSE); } */ break; } //////////////////////////////////////// case LIST_TYPE_TARGET: //////////////////////////////////////// { entity *group; // // Notify the group that it has been targeted // if (get_comms_model () == COMMS_MODEL_SERVER) { if (get_local_entity_int_value (sender, INT_TYPE_IDENTIFY_MOBILE)) { group = get_local_entity_parent (sender, LIST_TYPE_MEMBER); if (group) { notify_local_entity (ENTITY_MESSAGE_ENTITY_TARGETED, group, receiver, sender); } } } // // if targetting the player then insert into the gunship target list if not already there // if (sender == get_gunship_entity ()) { if (!get_local_entity_parent (receiver, LIST_TYPE_GUNSHIP_TARGET)) { if (get_local_entity_int_value (receiver, INT_TYPE_TARGET_TYPE) != TARGET_TYPE_INVALID) { if (get_local_entity_int_value (receiver, INT_TYPE_THREAT_TYPE) != THREAT_TYPE_INVALID) { insert_local_entity_into_parents_child_list (receiver, LIST_TYPE_GUNSHIP_TARGET, sender, NULL); } } } } break; } } return (TRUE); }
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 // ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// }
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 entity *create_local (entity_types type, int index, char *pargs) { entity *en; weapon *raw; int seed; viewpoint vp; //////////////////////////////////////// // // VALIDATE // //////////////////////////////////////// validate_local_create_entity_index (index); #if DEBUG_MODULE debug_log_entity_args (ENTITY_DEBUG_LOCAL, ENTITY_DEBUG_CREATE, NULL, type, index); #endif en = get_free_entity (index); if (en) { float dispersion; //////////////////////////////////////// // // MALLOC ENTITY DATA // //////////////////////////////////////// set_local_entity_type (en, type); raw = (weapon *) malloc_fast_mem (sizeof (weapon)); set_local_entity_data (en, raw); //////////////////////////////////////// // // INITIALISE ALL ENTITY DATA TO 'WORKING' DEFAULT VALUES // // DO NOT USE ACCESS FUNCTIONS // // DO NOT USE RANDOM VALUES // //////////////////////////////////////// memset (raw, 0, sizeof (weapon)); // // mobile // raw->mob.sub_type = ENTITY_SUB_TYPE_UNINITIALISED; raw->mob.position.x = MID_MAP_X; raw->mob.position.y = MID_MAP_Y; raw->mob.position.z = MID_MAP_Z; get_identity_matrix3x3 (raw->mob.attitude); raw->mob.alive = TRUE; // // weapon // raw->kill_code = WEAPON_KILL_CODE_OK; //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (entity_sub_type_weapon_valid (raw->mob.sub_type)); ASSERT (raw->launched_weapon_link.parent); ASSERT (raw->burst_size > 0); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// if (weapon_database[raw->mob.sub_type].acquire_parent_forward_velocity) { raw->mob.velocity = get_local_entity_float_value (raw->launched_weapon_link.parent, FLOAT_TYPE_VELOCITY); } else { // // overwrite attribute // raw->mob.velocity = 0.0; } raw->mob.velocity += weapon_database[raw->mob.sub_type].muzzle_velocity; seed = get_client_server_entity_random_number_seed (en); raw->mob.velocity += weapon_database[raw->mob.sub_type].muzzle_velocity_max_error * frand1x (&seed); raw->weapon_lifetime = weapon_database[raw->mob.sub_type].burn_time; raw->decoy_timer = get_decoy_timer_start_value (weapon_database[raw->mob.sub_type].decoy_type); // // detach weapon from launcher (get position and attitude) // detach_local_entity_weapon (raw->launched_weapon_link.parent, raw->mob.sub_type, raw->burst_size, &vp); raw->mob.position = vp.position; // arneh - add dispersion as random rotation in heading and pitch up to max error angle dispersion = weapon_database[raw->mob.sub_type].max_range_error_ratio; if (dispersion > 0.0) { matrix3x3 m; float heading = dispersion * sfrand1norm(), pitch = dispersion * sfrand1norm(); get_3d_transformation_matrix(m, heading, pitch, 0.0); multiply_matrix3x3_matrix3x3(raw->mob.attitude, vp.attitude, m); } else memcpy (raw->mob.attitude, vp.attitude, sizeof (matrix3x3)); // // interest level // set_local_entity_float_value (raw->launched_weapon_link.parent, FLOAT_TYPE_VIEW_INTEREST_LEVEL, DEFAULT_VIEW_INTEREST_LEVEL); //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_LAUNCHED_WEAPON, raw->launched_weapon_link.parent, NULL); if (raw->mob.target_link.parent) { insert_local_entity_into_parents_child_list (en, LIST_TYPE_TARGET, raw->mob.target_link.parent, NULL); } insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, get_local_sector_entity (&raw->mob.position), NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); if (tacview_is_logging()) write_tacview_new_unit(en); // // check if the weapon camera is primed and this weapon has been launched by the external view entity // if (get_camera_entity ()) { if (get_local_entity_int_value (get_camera_entity (), INT_TYPE_WEAPON_CAMERA_PRIMED)) { if (raw->launched_weapon_link.parent == get_external_view_entity ()) { if (get_local_entity_int_value (en, INT_TYPE_VIEWABLE_WEAPON)) { notify_local_entity (ENTITY_MESSAGE_SET_CAMERA_ACTION, get_camera_entity (), NULL, CAMERA_ACTION_WEAPON); set_local_entity_int_value (get_camera_entity (), INT_TYPE_WEAPON_CAMERA_PRIMED, FALSE); } } } } } return (en); }
void create_client_server_entity_weapon (entity *launcher, entity_sub_types weapon_sub_type, int weapon_index, int burst_size, int *smoke_trail_indices) { entity *force, *target, *weapon; meta_smoke_list_types smoke_trail_type; int i, num_smoke_trail_entities, valid_sound_effect, current_weapon_count, new_weapon_count; ASSERT (launcher); ASSERT (entity_sub_type_weapon_valid (weapon_sub_type)); // // get target // if (!(weapon_database[weapon_sub_type].weapon_class & (WEAPON_CLASS_DECOY | WEAPON_CLASS_CARGO | WEAPON_CLASS_DEBRIS))) { target = get_local_entity_parent (launcher, LIST_TYPE_TARGET); /* if (weapon_database[weapon_sub_type].hellfire_flight_profile) { if (get_local_entity_int_value (launcher, INT_TYPE_LOCK_ON_AFTER_LAUNCH)) { target = NULL; } } */ } else { target = NULL; } if (get_comms_model () == COMMS_MODEL_SERVER) { //////////////////////////////////////// // // SERVER/TX and SERVER/RX // //////////////////////////////////////// ASSERT (weapon_index == ENTITY_INDEX_DONT_CARE); ASSERT (burst_size == BURST_SIZE_DONT_CARE); ASSERT (!smoke_trail_indices); // NOTE: The clients' weapon counters lag the servers' so it is possible that the // client may unknowingly attempt to create more weapons than are available. // This is prone to happen during rapid firing. current_weapon_count = get_local_entity_weapon_count (launcher, weapon_sub_type); if (current_weapon_count > 0) { int loal_mode = weapon_database[weapon_sub_type].hellfire_flight_profile && get_local_entity_int_value (launcher, INT_TYPE_LOCK_ON_AFTER_LAUNCH); if (get_comms_data_flow () == COMMS_DATA_FLOW_RX) { set_force_local_entity_create_stack_attributes (TRUE); } // // get burst size wrt rate of fire // if (weapon_database[weapon_sub_type].rate_of_fire != FIRE_SINGLE_WEAPON) { float time_per_shot = weapon_database[weapon_sub_type].inverse_rate_of_fire * ONE_MINUTE; unsigned int* last_shot = NULL; switch (launcher->type) { case ENTITY_TYPE_HELICOPTER: last_shot = &((helicopter*)get_local_entity_data(launcher))->ac.weapon_salvo_timer; break; case ENTITY_TYPE_FIXED_WING: last_shot = &((fixed_wing*)get_local_entity_data(launcher))->ac.weapon_salvo_timer; break; case ENTITY_TYPE_ANTI_AIRCRAFT: last_shot = &((anti_aircraft*)get_local_entity_data(launcher))->vh.weapon_salvo_timer; break; case ENTITY_TYPE_PERSON: last_shot = &((person*)get_local_entity_data(launcher))->vh.weapon_salvo_timer; break; case ENTITY_TYPE_ROUTED_VEHICLE: last_shot = &((routed_vehicle*)get_local_entity_data(launcher))->vh.weapon_salvo_timer; break; case ENTITY_TYPE_SHIP_VEHICLE: last_shot = &((ship_vehicle*)get_local_entity_data(launcher))->vh.weapon_salvo_timer; break; } if (last_shot) { unsigned int current_time = get_system_time(); float elapsed_time = 1; if (*last_shot > 0) { if (current_time < *last_shot) return; elapsed_time = (current_time - *last_shot) * 0.001; } else elapsed_time = get_delta_time(); burst_size = (int)(weapon_database[weapon_sub_type].rate_of_fire * ONE_OVER_ONE_MINUTE * elapsed_time); if (burst_size < 1) { if (*last_shot == 0) // first shot in salvo always get fired burst_size = 1; else return; } if (*last_shot) *last_shot += (int)(burst_size * time_per_shot * 1000.0); else *last_shot = current_time; } else { ASSERT(FALSE); burst_size = 1; } } else { burst_size = 1; } // // set burst timer // valid_sound_effect = FALSE; if (get_local_entity_float_value (launcher, FLOAT_TYPE_WEAPON_BURST_TIMER) == 0.0) { set_local_entity_float_value (launcher, FLOAT_TYPE_WEAPON_BURST_TIMER, weapon_database[weapon_sub_type].burst_duration); valid_sound_effect = TRUE; } // // create weapon // weapon = create_local_entity ( ENTITY_TYPE_WEAPON, ENTITY_INDEX_DONT_CARE, ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, weapon_sub_type), ENTITY_ATTR_INT_VALUE (INT_TYPE_WEAPON_BURST_SIZE, burst_size), ENTITY_ATTR_INT_VALUE (INT_TYPE_WEAPON_MISSILE_PHASE, MISSILE_PHASE1), ENTITY_ATTR_INT_VALUE (INT_TYPE_LOCK_ON_AFTER_LAUNCH, loal_mode), ENTITY_ATTR_PARENT (LIST_TYPE_LAUNCHED_WEAPON, launcher), ENTITY_ATTR_PARENT (LIST_TYPE_TARGET, target), ENTITY_ATTR_END ); if (weapon) { // // send FIRE message to force (unless it's a decoy/cargo/debris being launched) // if ((target) && (!(weapon_database[weapon_sub_type].weapon_class & (WEAPON_CLASS_DECOY | WEAPON_CLASS_CARGO | WEAPON_CLASS_DEBRIS)))) { force = get_local_force_entity ((entity_sides) get_local_entity_int_value (target, INT_TYPE_SIDE)); if (force) { notify_local_entity (ENTITY_MESSAGE_ENTITY_FIRED_AT, force, launcher, target); } } // // create sound effect(s) // if (valid_sound_effect) { create_weapon_launched_sound_effects (launcher, weapon_sub_type); } // // create smoke trail // smoke_trail_type = (meta_smoke_list_types) get_local_entity_int_value (weapon, INT_TYPE_WEAPON_SMOKE_TRAIL_TYPE); if (smoke_trail_type != META_SMOKE_LIST_TYPE_NONE) { struct OBJECT_3D_BOUNDS *bounding_box; vec3d exhaust_offset; num_smoke_trail_entities = count_entities_in_meta_smoke_list (smoke_trail_type); ASSERT (num_smoke_trail_entities > 0); smoke_trail_indices = (int *) malloc_fast_mem (sizeof (int) * num_smoke_trail_entities); for (i = 0; i < num_smoke_trail_entities; i++) { smoke_trail_indices[i] = ENTITY_INDEX_DONT_CARE; } bounding_box = get_object_3d_bounding_box (get_local_entity_int_value (weapon, INT_TYPE_DEFAULT_3D_SHAPE)); if ((weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_PILOT) ||(weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_CO_PILOT)) { exhaust_offset.x = 0.0; exhaust_offset.y = 0.0; exhaust_offset.z = 0.0; } else { exhaust_offset.x = 0.0; exhaust_offset.y = 0.0; exhaust_offset.z = bounding_box->zmin; } create_meta_smoke_list_specified_offset (smoke_trail_type, weapon, &exhaust_offset, smoke_trail_indices); } transmit_entity_comms_message ( ENTITY_COMMS_CREATE_WEAPON, NULL, launcher, weapon_sub_type, get_local_entity_safe_index (weapon), burst_size, smoke_trail_indices ); if (smoke_trail_indices) { free_mem (smoke_trail_indices); } // // out of weapons (if infinite weapons then reload else select next weapon) // new_weapon_count = get_local_entity_weapon_count (launcher, weapon_sub_type); if (new_weapon_count <= 0) { #if !DEMO_VERSION if (get_local_entity_int_value (get_session_entity (), INT_TYPE_INFINITE_WEAPONS)) { weapon_config_types config_type; config_type = (weapon_config_types) get_local_entity_int_value (launcher, INT_TYPE_WEAPON_CONFIG_TYPE); set_client_server_entity_int_value (launcher, INT_TYPE_WEAPON_CONFIG_TYPE, config_type); } else #endif { // // play weapon out of ammo speech // play_entity_weapon_out_speech (launcher, weapon_sub_type); // // select next weapon // /* if (!(weapon_database[weapon_sub_type].weapon_class & (WEAPON_CLASS_DECOY | WEAPON_CLASS_CARGO | WEAPON_CLASS_DEBRIS))) { entity_sub_types next_weapon_sub_type; if (get_local_entity_int_value (launcher, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI) { next_weapon_sub_type = get_next_available_weapon_sub_type (launcher); } else { next_weapon_sub_type = ENTITY_SUB_TYPE_WEAPON_NO_WEAPON; } set_client_server_entity_int_value (launcher, INT_TYPE_SELECTED_WEAPON, next_weapon_sub_type); } */ } } else { int report_ammo_low_count; report_ammo_low_count = weapon_database[weapon_sub_type].report_ammo_low_count; if ((current_weapon_count > report_ammo_low_count) && (new_weapon_count <= report_ammo_low_count)) { // // play weapon low speech // play_entity_weapon_low_speech (launcher, weapon_sub_type); } else { // // weapon launch speech // play_entity_weapon_launched_speech (launcher, weapon_sub_type); } } } set_force_local_entity_create_stack_attributes (FALSE); } else { pause_client_server_continuous_weapon_sound_effect (launcher, weapon_sub_type); } } else { if (get_comms_data_flow () == COMMS_DATA_FLOW_TX) { //////////////////////////////////////// // // CLIENT/TX // //////////////////////////////////////// ASSERT (weapon_index == ENTITY_INDEX_DONT_CARE); ASSERT (burst_size == BURST_SIZE_DONT_CARE); ASSERT (!smoke_trail_indices); // NOTE: The clients' weapon counters lag the servers' so it is possible that the // client may unknowingly attempt to create more weapons than are available. // This is prone to happen during rapid firing. if (get_local_entity_weapon_available (launcher, weapon_sub_type)) { transmit_entity_comms_message ( ENTITY_COMMS_CREATE_WEAPON, NULL, launcher, weapon_sub_type, ENTITY_INDEX_DONT_CARE, burst_size, NULL ); } } else { //////////////////////////////////////// // // CLIENT/RX // //////////////////////////////////////// ASSERT (weapon_index != ENTITY_INDEX_DONT_CARE); ASSERT (burst_size > 0); set_force_local_entity_create_stack_attributes (TRUE); weapon = create_local_entity ( ENTITY_TYPE_WEAPON, weapon_index, ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, weapon_sub_type), ENTITY_ATTR_INT_VALUE (INT_TYPE_WEAPON_BURST_SIZE, burst_size), ENTITY_ATTR_PARENT (LIST_TYPE_LAUNCHED_WEAPON, launcher), ENTITY_ATTR_PARENT (LIST_TYPE_TARGET, target), ENTITY_ATTR_END ); ASSERT (weapon); // // create smoke trail // smoke_trail_type = (meta_smoke_list_types) get_local_entity_int_value (weapon, INT_TYPE_WEAPON_SMOKE_TRAIL_TYPE); if (smoke_trail_type != META_SMOKE_LIST_TYPE_NONE) { struct OBJECT_3D_BOUNDS *bounding_box; vec3d exhaust_offset; ASSERT (smoke_trail_indices); bounding_box = get_object_3d_bounding_box (get_local_entity_int_value (weapon, INT_TYPE_DEFAULT_3D_SHAPE)); if ((weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_PILOT) ||(weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_CO_PILOT)) { exhaust_offset.x = 0.0; exhaust_offset.y = 0.0; exhaust_offset.z = 0.0; } else { exhaust_offset.x = 0.0; exhaust_offset.y = 0.0; exhaust_offset.z = bounding_box->zmin; } create_meta_smoke_list_specified_offset (smoke_trail_type, weapon, &exhaust_offset, smoke_trail_indices); } else { ASSERT (!smoke_trail_indices); } set_force_local_entity_create_stack_attributes (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); }
void ship_vehicle_death_movement (entity *en) { ship_vehicle *raw; float speed, heading, pitch, roll; vec3d *pos, *velocity, new_pos; raw = get_local_entity_data (en); // // work out new position // velocity = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_MOTION_VECTOR); pos = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); new_pos.x = pos->x + (velocity->x * get_entity_movement_delta_time()); new_pos.y = pos->y + (velocity->y * get_entity_movement_delta_time()); new_pos.z = pos->z + (velocity->z * get_entity_movement_delta_time()); // // update velocity // velocity->x -= (velocity->x * 0.2 * get_entity_movement_delta_time ()); velocity->z -= (velocity->z * 0.2 * get_entity_movement_delta_time ()); velocity->y -= (SHIP_SINK_RATE * get_entity_movement_delta_time ()); speed = get_3d_vector_magnitude (velocity); set_local_entity_float_value (en, FLOAT_TYPE_VELOCITY, speed); // // update attitude // heading = get_heading_from_attitude_matrix (raw->vh.mob.attitude); pitch = get_pitch_from_attitude_matrix (raw->vh.mob.attitude); pitch += (SHIP_SINK_DELTA_PITCH_RATE * get_entity_movement_delta_time()); roll = get_roll_from_attitude_matrix (raw->vh.mob.attitude); roll += (SHIP_SINK_DELTA_ROLL_RATE * get_entity_movement_delta_time()); get_3d_transformation_matrix (raw->vh.mob.attitude, heading, pitch, roll); // // set new position // set_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &new_pos); clear_ship_fires (en, ENTITY_SUB_TYPE_EFFECT_SMOKE_LIST_FIRE); clear_ship_fires (en, ENTITY_SUB_TYPE_EFFECT_SMOKE_LIST_EXPLOSION_TRAIL); // // remove ship if totally obscured (i.e. sunk) // if (get_comms_model () == COMMS_MODEL_SERVER) { struct OBJECT_3D_BOUNDS *bounding_box; vec3d d; float obscured_altitude; bounding_box = get_object_3d_bounding_box (get_local_entity_int_value (en, INT_TYPE_OBJECT_3D_SHAPE)); d.x = bounding_box->xmax - bounding_box->xmin; d.y = bounding_box->ymax - bounding_box->ymin; d.z = bounding_box->zmax - bounding_box->zmin; obscured_altitude = -(0.5 * get_3d_vector_magnitude (&d)); if (new_pos.y < obscured_altitude) { // // ship is no longer visible // destroy_client_server_entity_family (en); } } }
static void kill_local (entity *en) { person *raw; int losses; 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); //////////////////////////////////////// // // VALIDATE // //////////////////////////////////////// //////////////////////////////////////// // // 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); // update person object damage_person_3d_object (en); group = get_local_entity_parent (en, LIST_TYPE_MEMBER); ASSERT (group); // // group losses // losses = get_local_entity_int_value (group, INT_TYPE_LOSSES); losses ++; set_local_entity_int_value (group, INT_TYPE_LOSSES, losses); //////////////////////////////////////// // // DESTROY COMPONENTS // //////////////////////////////////////// if (get_comms_model () == COMMS_MODEL_SERVER) { //////////////////////////////////////// // // SEND NOTIFY MESSAGES // //////////////////////////////////////// // // // 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 ("PS_DSTRY: killing person, 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); } } // // Release landing lock (if any) // //release_mobile_entity_landing_locks (en); } //////////////////////////////////////// // // UNLINK FROM SYSTEM // //////////////////////////////////////// // // person // // // vehicle // 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_MEMBER); 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); //unlink_local_entity_children (en, LIST_TYPE_SPECIAL_EFFECT); 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); set_local_entity_int_value (en, INT_TYPE_OPERATIONAL_STATE, OPERATIONAL_STATE_DEAD); // // 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)); if (get_comms_model () == COMMS_MODEL_SERVER) { create_client_server_object_killed_explosion_effect (en); } }
static void unpack_local_data (entity *en, entity_types type, pack_modes mode) { ASSERT ((mode >= 0) && (mode < NUM_PACK_MODES)); switch (mode) { //////////////////////////////////////// case PACK_MODE_SERVER_SESSION: case PACK_MODE_CLIENT_SESSION: //////////////////////////////////////// { int index; routed_vehicle *raw; node_link_data *route_data; // // create entity // index = unpack_entity_safe_index (); en = get_free_entity (index); set_local_entity_type (en, type); raw = (routed_vehicle *) malloc_fast_mem (sizeof (routed_vehicle)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (routed_vehicle)); // // unpack vehicle data (in exactly the same order as the data was packed) // unpack_vehicle_data (en, &raw->vh, mode); if (unpack_int_value (en, INT_TYPE_VALID)) { raw->vh.mob.velocity = 0.0; raw->desired_velocity = 0.0; } else { raw->vh.mob.velocity = unpack_float_value (en, FLOAT_TYPE_LOW_VELOCITY); raw->desired_velocity = unpack_float_value (en, FLOAT_TYPE_DESIRED_VELOCITY); } // // unpack routed data // if (unpack_int_value (en, INT_TYPE_VALID)) { raw->sub_waypoint_count = unpack_int_value (en, INT_TYPE_SUB_WAYPOINT_COUNT); raw->waypoint_next_index = unpack_int_value (en, INT_TYPE_WAYPOINT_NEXT_INDEX); raw->waypoint_this_index = unpack_int_value (en, INT_TYPE_WAYPOINT_THIS_INDEX); } // // turn lights on if necessary // set_vehicle_headlight_state (en, raw->vh.lights_on); // // setup waypoint route pointer // #if DEBUG_MODULE debug_log ("ROUTED ENTITY PACK: client setting up waypoint list pointer"); #endif route_data = get_road_sub_route (raw->waypoint_this_index, raw->waypoint_next_index, &index, NULL); if ((route_data) && (route_data->link_positions)) { raw->sub_route = route_data; } else { if ((raw->waypoint_this_index + raw->waypoint_next_index) != 0) { debug_log ("RV_PACK: WARNING NO SUB ROUTE FOUND BETWEEN %d AND %d", raw->waypoint_this_index, raw->waypoint_next_index); } } // // radar dish rotation (ok to use a random number as this is for visual effect only) // raw->vh.radar_rotation_state = frand1 (); set_routed_vehicle_id_number (en); set_initial_rotation_angle_of_routed_vehicle_wheels (raw->vh.inst3d); // // link into system // insert_local_entity_into_parents_child_list (en, LIST_TYPE_VIEW, get_camera_entity (), NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, get_local_sector_entity (&raw->vh.mob.position), NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); add_to_force_info (get_local_force_entity ((entity_sides) raw->vh.mob.side), en); // // attached smoke lists must be unpacked after the entity is linked into the world // unpack_routed_vehicle_meta_smoke_lists (en, mode); unpack_mobile_local_sound_effects (en, mode); break; } //////////////////////////////////////// case PACK_MODE_BROWSE_SESSION: //////////////////////////////////////// { break; } //////////////////////////////////////// case PACK_MODE_UPDATE_ENTITY: //////////////////////////////////////// { // // always use access functions to set the data // vec3d position; matrix3x3 attitude; int sub_waypoint_count; // // unpack all data (even if the echoed data is to be ignored) // unpack_vec3d (en, VEC3D_TYPE_POSITION, &position); unpack_attitude_matrix (en, attitude); sub_waypoint_count = unpack_int_value (en, INT_TYPE_SUB_WAYPOINT_COUNT); set_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &position); set_local_entity_attitude_matrix (en, attitude); set_local_entity_int_value (en, INT_TYPE_SUB_WAYPOINT_COUNT, sub_waypoint_count); // Vehicle is moving so sleep must equal 0 set_local_entity_float_value (en, FLOAT_TYPE_SLEEP, 0.0); break; } } }
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 unpack_local_data (entity *en, entity_types type, pack_modes mode) { ASSERT ((mode >= 0) && (mode < NUM_PACK_MODES)); switch (mode) { //////////////////////////////////////// case PACK_MODE_SERVER_SESSION: case PACK_MODE_CLIENT_SESSION: case PACK_MODE_BROWSE_SESSION: //////////////////////////////////////// { break; } //////////////////////////////////////// case PACK_MODE_UPDATE_ENTITY: //////////////////////////////////////// { vec3d v; // // always use access functions to set the data // set_local_entity_float_value (en, FLOAT_TYPE_ELAPSED_TIME, unpack_float_value (en, FLOAT_TYPE_ELAPSED_TIME)); set_local_entity_float_value (en, FLOAT_TYPE_LIGHTNING_TIMER, unpack_float_value (en, FLOAT_TYPE_LIGHTNING_TIMER)); // // rain effect // set_local_entity_float_value (en, FLOAT_TYPE_WEATHER_RADIUS, unpack_float_value (en, FLOAT_TYPE_WEATHER_RADIUS)); unpack_vec3d (en, VEC3D_TYPE_WEATHER_POSITION, &v); set_local_entity_vec3d (en, VEC3D_TYPE_WEATHER_POSITION, &v); unpack_vec3d (en, VEC3D_TYPE_WEATHER_VELOCITY, &v); set_local_entity_vec3d (en, VEC3D_TYPE_WEATHER_VELOCITY, &v); // // wind effect // set_local_entity_float_value (en, FLOAT_TYPE_WIND_EFFECT_RADIUS, unpack_float_value (en, FLOAT_TYPE_WIND_EFFECT_RADIUS)); set_local_entity_float_value (en, FLOAT_TYPE_WIND_GUSTING_VALUE, unpack_float_value (en, FLOAT_TYPE_WIND_GUSTING_VALUE)); unpack_vec3d (en, VEC3D_TYPE_WIND_DIRECTION_VECTOR, &v); set_local_entity_vec3d (en, VEC3D_TYPE_WIND_DIRECTION_VECTOR, &v); unpack_vec3d (en, VEC3D_TYPE_WIND_EFFECT_POSITION, &v); set_local_entity_vec3d (en, VEC3D_TYPE_WIND_EFFECT_POSITION, &v); unpack_vec3d (en, VEC3D_TYPE_WIND_EFFECT_VELOCITY, &v); set_local_entity_vec3d (en, VEC3D_TYPE_WIND_EFFECT_VELOCITY, &v); // set_local_entity_int_value (en, INT_TYPE_WEATHER_INCREASING, unpack_int_value (en, INT_TYPE_WEATHER_INCREASING)); set_local_entity_int_value (en, INT_TYPE_WIND_INCREASING, unpack_int_value (en, INT_TYPE_WIND_INCREASING)); set_display_campaign_timer_valid (TRUE); break; } } }
entity *regen_update (entity *en) { regen_management_element *m1; entity_sub_types member_type, group_type; entity *wp, *task, *group, *member, *building, *force_en, *landing, *keysite; unsigned int member_number; int reserve_count; force *force_raw; regen *raw; regen_list_element *e1; raw = (regen *) get_local_entity_data (en); wp = get_local_entity_parent (en, LIST_TYPE_CURRENT_WAYPOINT); task = get_local_entity_parent (wp, LIST_TYPE_WAYPOINT); landing = get_local_entity_parent (task, LIST_TYPE_UNASSIGNED_TASK); keysite = get_local_entity_parent (landing, LIST_TYPE_LANDING_SITE); force_en = get_local_force_entity ((entity_sides) raw->side); force_raw = (force *) get_local_entity_data (force_en); group_type = NUM_ENTITY_SUB_TYPE_GROUPS; m1 = ®en_manager [raw->side][raw->sub_type]; // // is there anything in the regen queues? // if (m1->count == 0) { return NULL; } // // Can regen operate // building = raw->member_root.first_child; if ((!get_local_entity_int_value (building, INT_TYPE_ALIVE)) || (get_local_entity_int_value (keysite, INT_TYPE_KEYSITE_USABLE_STATE) != KEYSITE_STATE_USABLE)) { #if DEBUG_MODULE debug_log ("RG_UPDT: keysite %s too damaged to regen", get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME)); #endif return NULL; } e1 = ®en_queue [raw->side][raw->sub_type][m1->front]; ASSERT (e1->type != -1); ASSERT (e1->sub_type != -1); ASSERT (e1->group != -1); // is there a reserve of this type? if ((e1->type == ENTITY_TYPE_FIXED_WING) || (e1->type == ENTITY_TYPE_HELICOPTER)) { reserve_count = force_raw->force_info_reserve_hardware[aircraft_database[e1->sub_type].force_info_catagory]; } else { reserve_count = force_raw->force_info_reserve_hardware[vehicle_database[e1->sub_type].force_info_catagory]; } if (reserve_count <= 0) { return NULL; } #if DEBUG_MODULE debug_log ("RG_UPDT: Trying to Regen %s Sub Type %d at %s - reserve count %d", get_entity_type_name (e1->type), e1->sub_type, get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME), reserve_count); #endif // // Don't regen if PLAYER landed there // group = get_local_entity_first_child (keysite, LIST_TYPE_KEYSITE_GROUP); while (group) { member = get_local_entity_first_child (group, LIST_TYPE_MEMBER); while (member) { if (get_local_entity_int_value (member, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI) { if (get_local_entity_int_value (member, INT_TYPE_LANDED)) { #if DEBUG_MODULE debug_log ("RG_UPDT: PLAYER landed at keysite %s, can't regen", get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME)); #endif return NULL; } } member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER); } group = get_local_entity_child_succ (group, LIST_TYPE_KEYSITE_GROUP); } group_type = e1->group; member_type = e1->sub_type; //////////////////////////////////////////////////////////////////////////// // Dont regen people or transport aircraft in apache havoc campaign as airport might not be correct (landing routes etc) //////////////////////////////////////////////////////////////////////////// if (get_local_entity_int_value (get_session_entity (), INT_TYPE_CAMPAIGN_REQUIRES_APACHE_HAVOC)) { switch (get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE)) { case ENTITY_SUB_TYPE_REGEN_PEOPLE: { #if DEBUG_MODULE debug_log ("RG_UPDT: Stopping Regening People - wrong warzone"); #endif return NULL; } case ENTITY_SUB_TYPE_REGEN_FIXED_WING: { if (group_database [group_type].default_landing_type == ENTITY_SUB_TYPE_LANDING_FIXED_WING_TRANSPORT) { #if DEBUG_MODULE debug_log ("RG_UPDT: Stopping Regening Transport aircraft - wrong warzone"); #endif return NULL; } } } } //////////////////////////////////////////////////////////////////////////// // Dont regen people or transport aircraft in apache havoc campaign as airport might not be correct (landing routes etc) //////////////////////////////////////////////////////////////////////////// if (group_type != NUM_ENTITY_SUB_TYPE_GROUPS) { int route_node; entity *building, *member, *guide, *group = NULL; group = create_landing_faction_members (keysite, member_type, group_type, 1, wp, &raw->position); if (group) { // // Assign closest route_node (only needed for routed vehicles) // if (get_local_entity_int_value (group, INT_TYPE_FRONTLINE)) { route_node = get_closest_side_road_node ((entity_sides) get_local_entity_int_value (group, INT_TYPE_SIDE), &raw->position, 5 * KILOMETRE); set_client_server_entity_int_value (group, INT_TYPE_ROUTE_NODE, route_node); } // // // member = get_local_entity_first_child (group, LIST_TYPE_MEMBER); // // close members doors // close_client_server_entity_cargo_doors (member); close_client_server_entity_loading_doors (member); // // open building doors // building = get_local_entity_first_child (en, LIST_TYPE_MEMBER); open_client_server_entity_loading_doors (building); set_local_entity_float_value (building, FLOAT_TYPE_LOADING_DOOR_TIMER, 30.0); // // create guide entity for task (TEST) // // Debug for Transport aircraft. // Locate nearest Transport landing wp and insert into it if (group_database [group_type].default_landing_type == ENTITY_SUB_TYPE_LANDING_FIXED_WING_TRANSPORT) { float range, best_range; entity *transport_wp, *transport_task, *transport_landing; best_range = 999999999.0; transport_landing = get_local_entity_landing_entity (keysite, ENTITY_SUB_TYPE_LANDING_FIXED_WING_TRANSPORT); if (transport_landing) { transport_task = get_local_landing_entity_task (transport_landing, ENTITY_SUB_TYPE_TASK_LANDING); ASSERT (transport_task); transport_wp = get_local_entity_first_child (transport_task, LIST_TYPE_WAYPOINT); ASSERT (transport_wp); while (transport_wp) { range = get_sqr_2d_range (get_local_entity_vec3d_ptr (transport_wp, VEC3D_TYPE_POSITION), get_local_entity_vec3d_ptr (building, VEC3D_TYPE_POSITION)); if (range < best_range) { wp = transport_wp; task = transport_task; best_range = range; } transport_wp = get_local_entity_child_succ (transport_wp, LIST_TYPE_WAYPOINT); } } } // Debug for Transport aircraft. member_number = get_local_entity_int_value (member, INT_TYPE_GROUP_MEMBER_NUMBER); guide = create_client_server_guide_entity (task, wp, (1 << member_number)); attach_group_to_guide_entity (group, guide); attach_group_member_to_guide_entity (member, guide); //#if DEBUG_MODULE { entity *keysite; keysite = get_local_entity_parent (landing, LIST_TYPE_LANDING_SITE); member = get_local_entity_first_child (group, LIST_TYPE_MEMBER); debug_log ("RG_UPDT: %s creating %s (%d) at keysite %s free landing sites %d, reserved %d, lock %d, available lock: %d", entity_side_names [get_local_entity_int_value (keysite, INT_TYPE_SIDE)], get_local_entity_type_name (member), get_local_entity_index (member), get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME), get_local_entity_int_value (landing, INT_TYPE_FREE_LANDING_SITES), get_local_entity_int_value (landing, INT_TYPE_RESERVED_LANDING_SITES), get_local_entity_int_value (landing, INT_TYPE_LANDING_LOCK), check_available_landing_route_lock (landing) ); if ((e1->type == ENTITY_TYPE_FIXED_WING) || (e1->type == ENTITY_TYPE_HELICOPTER)) { debug_log("%s reserves left: %d", force_info_catagory_names[aircraft_database[e1->sub_type].force_info_catagory], force_raw->force_info_reserve_hardware[aircraft_database[e1->sub_type].force_info_catagory] ); } else { debug_log("%s reserves left: %d", force_info_catagory_names[vehicle_database[e1->sub_type].force_info_catagory], force_raw->force_info_reserve_hardware[vehicle_database[e1->sub_type].force_info_catagory] ); } } //#endif #if DEBUG_MODULE switch (e1->type) { case ENTITY_TYPE_FIXED_WING: case ENTITY_TYPE_HELICOPTER: { ASSERT (regen_ac_debug[e1->sub_type] > 0); break; } case ENTITY_TYPE_ROUTED_VEHICLE: case ENTITY_TYPE_SHIP_VEHICLE: case ENTITY_TYPE_PERSON: { ASSERT (regen_vh_debug[e1->sub_type] > 0); break; } default: { debug_fatal ("RG_UPDT: Unknown entity type for debug"); } } #endif // update markers regen_queue_use ((entity_sides) raw->side, (raw->sub_type)); return member; } } else { #if DEBUG_MODULE >= 2 debug_log ("RG_UPDT: not creating anything at keysite %s free landing sites %d, reserved %d, lock %d", get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME), get_local_entity_int_value (landing, INT_TYPE_FREE_LANDING_SITES), get_local_entity_int_value (landing, INT_TYPE_RESERVED_LANDING_SITES), check_available_landing_route_lock (landing)); #endif } return NULL; }