static int response_to_unlink_child (entity_messages message, entity *receiver, entity *sender, va_list pargs) { camera *raw; list_types list_type; #if DEBUG_MODULE debug_log_entity_message (message, receiver, sender, pargs); #endif raw = get_local_entity_data (receiver); list_type = va_arg (pargs, list_types); switch (list_type) { //////////////////////////////////////// case LIST_TYPE_VIEW: //////////////////////////////////////// { if (raw->external_view_entity == sender) { raw->external_view_entity = NULL; } notify_view_menu_of_view_list_change (sender); break; } //////////////////////////////////////// case LIST_TYPE_VIEW_WEAPON: //////////////////////////////////////// { ASSERT (sender); if (get_view_mode () == VIEW_MODE_EXTERNAL) { if (get_local_entity_int_value (get_camera_entity (), INT_TYPE_CAMERA_MODE) == CAMERA_MODE_WEAPON) { notify_local_entity (ENTITY_MESSAGE_SET_CAMERA_ACTION, get_camera_entity (), NULL, CAMERA_ACTION_WEAPON_EXPLOSION); reset_weapon_explosion_camera_position (get_local_entity_vec3d_ptr (sender, VEC3D_TYPE_POSITION)); } } break; } } return (TRUE); }
void set_chase_camera_view_target_to_source (entity *source, entity *target) { camera *raw; float length; vec3d *source_position, *target_position, direction; ASSERT (source); ASSERT (target); ASSERT (get_camera_entity ()); raw = get_local_entity_data (get_camera_entity ()); source_position = get_local_entity_vec3d_ptr (source, VEC3D_TYPE_POSITION); target_position = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION); direction.x = source_position->x - target_position->x; direction.y = source_position->y - target_position->y; direction.z = source_position->z - target_position->z; length = (direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&direction, length); raw->chase_camera_heading = atan2 (direction.x, direction.z); if (raw->chase_camera_lock_rotate) { raw->chase_camera_heading -= get_local_entity_float_value (target, FLOAT_TYPE_HEADING); raw->chase_camera_heading = wrap_angle (raw->chase_camera_heading); } raw->chase_camera_pitch = asin (direction.y); } }
void restore_reverse_tactical_camera_values (void) { camera *raw; ASSERT (get_camera_entity ()); raw = get_local_entity_data (get_camera_entity ()); raw->position = raw->stored_reverse_tactical_position; raw->motion_vector = raw->stored_reverse_tactical_motion_vector; memcpy (raw->attitude, raw->stored_reverse_tactical_attitude, sizeof (matrix3x3)); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; routed_vehicle *raw; entity_sub_types group_sub_type; float heading; vec3d *face_normal; //////////////////////////////////////// // // 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) { //////////////////////////////////////// // // MALLOC ENTITY DATA // //////////////////////////////////////// set_local_entity_type (en, type); raw = malloc_fast_mem (sizeof (routed_vehicle)); 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 (routed_vehicle)); // // mobile // raw->vh.mob.sub_type = ENTITY_SUB_TYPE_UNINITIALISED; raw->vh.mob.position.x = MID_MAP_X; raw->vh.mob.position.y = MID_MAP_Y; raw->vh.mob.position.z = MID_MAP_Z; get_identity_matrix3x3 (raw->vh.mob.attitude); raw->vh.mob.alive = TRUE; raw->vh.mob.side = ENTITY_SIDE_UNINITIALISED; raw->vh.operational_state = OPERATIONAL_STATE_UNKNOWN; // // vehicle // raw->vh.object_3d_shape = OBJECT_3D_INVALID_OBJECT_INDEX; raw->vh.weapon_config_type = WEAPON_CONFIG_TYPE_UNINITIALISED; raw->vh.selected_weapon = ENTITY_SUB_TYPE_WEAPON_NO_WEAPON; raw->vh.weapon_vector.x = 0.0; raw->vh.weapon_vector.y = 0.0; raw->vh.weapon_vector.z = 1.0; raw->vh.weapon_to_target_vector.x = 0.0; raw->vh.weapon_to_target_vector.y = 0.0; raw->vh.weapon_to_target_vector.z = -1.0; raw->vh.loading_door_state = VEHICLE_LOADING_DOORS_OPEN_FLOAT_VALUE; // // routed // //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (raw->vh.member_link.parent); ASSERT (get_local_entity_type (raw->vh.member_link.parent) == ENTITY_TYPE_GROUP); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// raw->sub_route = NULL; // // side // if (raw->vh.mob.side == ENTITY_SIDE_UNINITIALISED) { raw->vh.mob.side = get_local_entity_int_value (raw->vh.member_link.parent, INT_TYPE_SIDE); } ASSERT (raw->vh.mob.side != ENTITY_SIDE_NEUTRAL); // // sub_type // if (raw->vh.mob.sub_type == ENTITY_SUB_TYPE_UNINITIALISED) { group_sub_type = get_local_entity_int_value (raw->vh.member_link.parent, INT_TYPE_ENTITY_SUB_TYPE); if (raw->vh.mob.side == ENTITY_SIDE_BLUE_FORCE) { raw->vh.mob.sub_type = group_database[group_sub_type].default_blue_force_sub_type; } else { raw->vh.mob.sub_type = group_database[group_sub_type].default_red_force_sub_type; } } ASSERT (entity_sub_type_vehicle_valid (raw->vh.mob.sub_type)); // // 3D shape // if (raw->vh.object_3d_shape == OBJECT_3D_INVALID_OBJECT_INDEX) { raw->vh.object_3d_shape = vehicle_database[raw->vh.mob.sub_type].default_3d_shape; } // // weapon config // if (raw->vh.weapon_config_type == WEAPON_CONFIG_TYPE_UNINITIALISED) { raw->vh.weapon_config_type = vehicle_database[raw->vh.mob.sub_type].default_weapon_config_type; } ASSERT (weapon_config_type_valid (raw->vh.weapon_config_type)); // // damage levels // raw->vh.damage_level = vehicle_database[raw->vh.mob.sub_type].initial_damage_level; // // radar dish rotation (ok to use a random number as this is for visual effect only) // raw->vh.radar_rotation_state = frand1 (); //////////////////////////////////////// // // BUILD COMPONENTS // //////////////////////////////////////// // // 3D object // raw->vh.inst3d = construct_3d_object (raw->vh.object_3d_shape); set_routed_vehicle_id_number (en); set_initial_rotation_angle_of_routed_vehicle_wheels (raw->vh.inst3d); // // align with terrain // get_3d_terrain_point_data (raw->vh.mob.position.x, raw->vh.mob.position.z, &raw->vh.terrain_info); heading = get_heading_from_attitude_matrix (raw->vh.mob.attitude); face_normal = get_3d_terrain_point_data_normal (&raw->vh.terrain_info); get_3d_transformation_matrix_from_face_normal_and_heading (raw->vh.mob.attitude, face_normal, heading); // // weapon config // raw->vh.weapon_package_status_array = malloc_fast_mem (SIZE_WEAPON_PACKAGE_STATUS_ARRAY); memset (raw->vh.weapon_package_status_array, 0, SIZE_WEAPON_PACKAGE_STATUS_ARRAY); load_local_entity_weapon_config (en); // // update force info // add_to_force_info (get_local_force_entity (raw->vh.mob.side), en); //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_MEMBER, raw->vh.member_link.parent, raw->vh.member_link.child_pred); // // insert into LIST_TYPE_MEMBER before LIST_TYPE_VIEW // insert_local_entity_into_parents_child_list (en, LIST_TYPE_VIEW, get_camera_entity (), get_local_entity_view_list_pred (en)); 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); } return (en); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; camera *raw; //////////////////////////////////////// // // 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); ASSERT (!get_camera_entity ()); if (en) { //////////////////////////////////////// // // MALLOC ENTITY DATA // //////////////////////////////////////// set_local_entity_type (en, type); raw = (camera *) malloc_fast_mem (sizeof (camera)); 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 (camera)); raw->position.x = MID_MAP_X; raw->position.y = MID_MAP_Y; raw->position.z = MID_MAP_Z; raw->offset.x = 0; raw->offset.y = 0; raw->offset.z = 0; raw->offset_movement.x = 0; raw->offset_movement.y = 0; raw->offset_movement.z = 0; raw->turbulence_offset.x = 0.0; raw->turbulence_offset.y = 0.0; raw->turbulence_offset.z = 0.0; raw->turbulence_movement.x = 0.0; raw->turbulence_movement.y = 0.0; raw->turbulence_movement.z = 0.0; get_identity_matrix3x3 (raw->attitude); raw->camera_mode = CAMERA_MODE_CHASE; raw->chase_camera_lock_rotate = TRUE; reset_chase_camera_position (raw); reset_cinematic_camera_for_new_view_entity (raw); //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); set_camera_entity (en); } return (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; } } }
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); } }
void update_transitional_weather (entity *en) { vec3d *camera_pos; session *raw; ASSERT (en); raw = (session *) get_local_entity_data (en); if (raw->local_weather_model) { // // local weather model // if (raw->weather_radius == 0.0) { // // weather is fine all across the map // raw->weather_mode = WEATHERMODE_DRY; raw->target_weather_mode = WEATHERMODE_DRY; raw->weather_mode_transitional_status = 1.0; } else { // // there is some bad weather somewhere on the map // if (in_cockpit) { camera_pos = get_local_entity_vec3d_ptr (get_gunship_entity (), VEC3D_TYPE_POSITION); } else { camera_pos = get_local_entity_vec3d_ptr (get_camera_entity (), VEC3D_TYPE_POSITION); } get_session_weather_at_point (camera_pos, &(raw->weather_mode), &(raw->target_weather_mode), &(raw->weather_mode_transitional_status)); // // lightning effect // update_lightning_effect (en); } // // move weather // raw->weather_position.x += (raw->weather_velocity.x * get_delta_time ()); raw->weather_position.z += (raw->weather_velocity.z * get_delta_time ()); // // "bounce" weather of sides of map // if (raw->weather_position.x < MIN_MAP_X) { raw->weather_position.x = MIN_MAP_X; raw->weather_velocity.x = -raw->weather_velocity.x; } else if (raw->weather_position.x >= MAX_MAP_X) { raw->weather_position.x = MAX_MAP_X - 1.0; raw->weather_velocity.x = -raw->weather_velocity.x; } if (raw->weather_position.z < MIN_MAP_Z) { raw->weather_position.z = MIN_MAP_Z; raw->weather_velocity.z = -raw->weather_velocity.z; } else if (raw->weather_position.z >= MAX_MAP_Z) { raw->weather_position.z = MAX_MAP_Z - 1.0; raw->weather_velocity.z = -raw->weather_velocity.z; } // // expand / contract weather radius // if (raw->weather_increasing) { raw->weather_radius += (WEATHER_EXPANSION_RATE * get_delta_time ()); if (raw->weather_radius > MAX_WEATHER_RADIUS) { raw->weather_increasing = FALSE; raw->weather_radius = MAX_WEATHER_RADIUS; } } else { raw->weather_radius -= (WEATHER_EXPANSION_RATE * get_delta_time ()); if (raw->weather_radius < MIN_WEATHER_RADIUS) { raw->weather_increasing = TRUE; raw->weather_radius = MIN_WEATHER_RADIUS; } } } else { // // global weather model // if (raw->weather_mode != raw->target_weather_mode) { raw->weather_mode_transitional_status += get_delta_time () / raw->weather_mode_transitional_period; if (raw->weather_mode_transitional_status >= 1.0) { raw->weather_mode = raw->target_weather_mode; raw->weather_mode_transitional_status = 0.0; } } else { raw->weather_mode_transitional_status = 0.0; } } // // move wind // raw->wind_effect_position.x += (raw->wind_effect_velocity.x * get_delta_time ()); raw->wind_effect_position.z += (raw->wind_effect_velocity.z * get_delta_time ()); // // "bounce" wind_effect of sides of map // if (raw->wind_effect_position.x < MIN_MAP_X) { raw->wind_effect_position.x = MIN_MAP_X; raw->wind_effect_velocity.x = -raw->wind_effect_velocity.x; } else if (raw->wind_effect_position.x >= MAX_MAP_X) { raw->wind_effect_position.x = MAX_MAP_X - 1.0; raw->wind_effect_velocity.x = -raw->wind_effect_velocity.x; } if (raw->wind_effect_position.z < MIN_MAP_Z) { raw->wind_effect_position.z = MIN_MAP_Z; raw->wind_effect_velocity.z = -raw->wind_effect_velocity.z; } else if (raw->wind_effect_position.z >= MAX_MAP_Z) { raw->wind_effect_position.z = MAX_MAP_Z - 1.0; raw->wind_effect_velocity.z = -raw->wind_effect_velocity.z; } // // increase gusting value // raw->wind_gusting_value += (get_delta_time () * WIND_GUST_FREQUENCY); while (raw->wind_gusting_value >= 1.0) { raw->wind_gusting_value -= 1.0; } // // expand / contract wind_effect radius // if (raw->wind_increasing) { raw->wind_effect_radius += (WIND_EXPANSION_RATE * get_delta_time ()); if (raw->wind_effect_radius > MAX_WIND_RADIUS) { raw->wind_increasing = FALSE; raw->wind_effect_radius = MAX_WIND_RADIUS; } } else { raw->wind_effect_radius -= (WIND_EXPANSION_RATE * get_delta_time ()); if (raw->wind_effect_radius < MIN_WIND_RADIUS) { raw->wind_increasing = TRUE; raw->wind_effect_radius = MIN_WIND_RADIUS; } } // // set wind direction // raw->wind_direction_vector.x = raw->wind_effect_position.x - MID_MAP_X; raw->wind_direction_vector.y = 0.0; raw->wind_direction_vector.z = raw->wind_effect_position.z - MID_MAP_Z; normalise_any_3d_vector (&raw->wind_direction_vector); }
void unpack_local_session_data (pack_modes mode) { session *raw; entity *en; int index; ASSERT ((mode >= 0) && (mode < NUM_PACK_MODES)); switch (mode) { //////////////////////////////////////// case PACK_MODE_SERVER_SESSION: //////////////////////////////////////// { en = get_session_entity (); ASSERT (en); raw = (session *) get_local_entity_data (en); raw->version_number = unpack_int_value (en, INT_TYPE_VERSION_NUMBER); unpack_list_root (en, LIST_TYPE_FORCE, &raw->force_root); // special_effect_root // update_link raw->elapsed_time = unpack_float_value (en, FLOAT_TYPE_ELAPSED_TIME); raw->lightning_timer = unpack_float_value (en, FLOAT_TYPE_LIGHTNING_TIMER); raw->start_time = unpack_float_value (en, FLOAT_TYPE_START_TIME); // time_of_day_resync raw->time_of_day_acceleration = unpack_float_value (en, FLOAT_TYPE_TIME_OF_DAY_ACCELERATION); raw->fog_of_war_maximum_value = unpack_float_value (en, FLOAT_TYPE_FOG_OF_WAR_MAXIMUM_VALUE); // // rain effect // raw->weather_radius = unpack_float_value (en, FLOAT_TYPE_WEATHER_RADIUS); raw->weather_mode_transitional_period = unpack_float_value (en, FLOAT_TYPE_WEATHER_MODE_TRANSITIONAL_PERIOD); raw->weather_mode_transitional_status = unpack_float_value (en, FLOAT_TYPE_WEATHER_MODE_TRANSITIONAL_STATUS); raw->weather_mode = (weathermodes) unpack_int_value (en, INT_TYPE_WEATHER_MODE); raw->target_weather_mode = (weathermodes) unpack_int_value (en, INT_TYPE_TARGET_WEATHER_MODE); unpack_vec3d (en, VEC3D_TYPE_WEATHER_POSITION, &raw->weather_position); unpack_vec3d (en, VEC3D_TYPE_WEATHER_VELOCITY, &raw->weather_velocity); // // wind effect // raw->wind_effect_radius = unpack_float_value (en, FLOAT_TYPE_WIND_EFFECT_RADIUS); raw->wind_gusting_value = unpack_float_value (en, FLOAT_TYPE_WIND_GUSTING_VALUE); raw->wind_minimum_speed = unpack_float_value (en, FLOAT_TYPE_WIND_MINIMUM_SPEED); raw->wind_maximum_speed = unpack_float_value (en, FLOAT_TYPE_WIND_MAXIMUM_SPEED); unpack_vec3d (en, VEC3D_TYPE_WIND_DIRECTION_VECTOR, &raw->wind_direction_vector); unpack_vec3d (en, VEC3D_TYPE_WIND_EFFECT_POSITION, &raw->wind_effect_position); unpack_vec3d (en, VEC3D_TYPE_WIND_EFFECT_VELOCITY, &raw->wind_effect_velocity); // raw->day_segment_type = (day_segment_types) unpack_int_value (en, INT_TYPE_DAY_SEGMENT_TYPE); raw->population_x_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MIN); raw->population_x_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MAX); raw->population_z_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MIN); raw->population_z_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MAX); raw->campaign_medal = unpack_int_value (en, INT_TYPE_CAMPAIGN_MEDAL); raw->campaign_requires_apache_havoc = unpack_int_value (en, INT_TYPE_CAMPAIGN_REQUIRES_APACHE_HAVOC); raw->auto_assign_gunship = unpack_int_value (en, INT_TYPE_AUTO_ASSIGN_GUNSHIP); raw->infinite_fuel = unpack_int_value (en, INT_TYPE_INFINITE_FUEL); raw->infinite_weapons = unpack_int_value (en, INT_TYPE_INFINITE_WEAPONS); raw->suppress_ai_fire = unpack_int_value (en, INT_TYPE_SUPPRESS_AI_FIRE); raw->invulnerable_from_collisions = unpack_int_value (en, INT_TYPE_INVULNERABLE_FROM_COLLISIONS); raw->invulnerable_from_weapons = unpack_int_value (en, INT_TYPE_INVULNERABLE_FROM_WEAPONS); raw->cheats_enabled = unpack_int_value (en, INT_TYPE_CHEATS_ENABLED); raw->skip_night_time = unpack_int_value (en, INT_TYPE_SKIP_NIGHT_TIME); raw->weather_increasing = unpack_int_value (en, INT_TYPE_WEATHER_INCREASING); raw->wind_increasing = unpack_int_value (en, INT_TYPE_WIND_INCREASING); raw->local_weather_model = unpack_int_value (en, INT_TYPE_LOCAL_WEATHER_MODEL); break; } //////////////////////////////////////// case PACK_MODE_CLIENT_SESSION: //////////////////////////////////////// { // // create entity // ASSERT (!get_session_entity ()); index = unpack_entity_safe_index (); en = get_free_entity (index); set_local_entity_type (en, ENTITY_TYPE_SESSION); raw = (session *) malloc_fast_mem (sizeof (session)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (session)); // // unpack data (in exactly the same order as the data was packed) // raw->version_number = unpack_int_value (en, INT_TYPE_VERSION_NUMBER); raw->session_complete = unpack_int_value (en, INT_TYPE_SESSION_COMPLETE); unpack_list_root (en, LIST_TYPE_FORCE, &raw->force_root); unpack_list_root (en, LIST_TYPE_SPECIAL_EFFECT, &raw->special_effect_root); // update_link raw->elapsed_time = unpack_float_value (en, FLOAT_TYPE_ELAPSED_TIME); raw->lightning_timer = unpack_float_value (en, FLOAT_TYPE_LIGHTNING_TIMER); raw->start_time = unpack_float_value (en, FLOAT_TYPE_START_TIME); // time_of_day_resync raw->time_of_day_acceleration = unpack_float_value (en, FLOAT_TYPE_TIME_OF_DAY_ACCELERATION); raw->fog_of_war_maximum_value = unpack_float_value (en, FLOAT_TYPE_FOG_OF_WAR_MAXIMUM_VALUE); // // rain effect // raw->weather_radius = unpack_float_value (en, FLOAT_TYPE_WEATHER_RADIUS); raw->weather_mode_transitional_period = unpack_float_value (en, FLOAT_TYPE_WEATHER_MODE_TRANSITIONAL_PERIOD); raw->weather_mode_transitional_status = unpack_float_value (en, FLOAT_TYPE_WEATHER_MODE_TRANSITIONAL_STATUS); raw->weather_mode = (weathermodes) unpack_int_value (en, INT_TYPE_WEATHER_MODE); raw->target_weather_mode = (weathermodes) unpack_int_value (en, INT_TYPE_TARGET_WEATHER_MODE); unpack_vec3d (en, VEC3D_TYPE_WEATHER_POSITION, &raw->weather_position); unpack_vec3d (en, VEC3D_TYPE_WEATHER_VELOCITY, &raw->weather_velocity); // // wind effect // raw->wind_effect_radius = unpack_float_value (en, FLOAT_TYPE_WIND_EFFECT_RADIUS); raw->wind_gusting_value = unpack_float_value (en, FLOAT_TYPE_WIND_GUSTING_VALUE); raw->wind_minimum_speed = unpack_float_value (en, FLOAT_TYPE_WIND_MINIMUM_SPEED); raw->wind_maximum_speed = unpack_float_value (en, FLOAT_TYPE_WIND_MAXIMUM_SPEED); unpack_vec3d (en, VEC3D_TYPE_WIND_DIRECTION_VECTOR, &raw->wind_direction_vector); unpack_vec3d (en, VEC3D_TYPE_WIND_EFFECT_POSITION, &raw->wind_effect_position); unpack_vec3d (en, VEC3D_TYPE_WIND_EFFECT_VELOCITY, &raw->wind_effect_velocity); // raw->day_segment_type = (day_segment_types) unpack_int_value (en, INT_TYPE_DAY_SEGMENT_TYPE); raw->population_x_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MIN); raw->population_x_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MAX); raw->population_z_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MIN); raw->population_z_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MAX); raw->campaign_medal = unpack_int_value (en, INT_TYPE_CAMPAIGN_MEDAL); raw->campaign_requires_apache_havoc = unpack_int_value (en, INT_TYPE_CAMPAIGN_REQUIRES_APACHE_HAVOC); raw->auto_assign_gunship = unpack_int_value (en, INT_TYPE_AUTO_ASSIGN_GUNSHIP); raw->infinite_fuel = unpack_int_value (en, INT_TYPE_INFINITE_FUEL); raw->infinite_weapons = unpack_int_value (en, INT_TYPE_INFINITE_WEAPONS); raw->suppress_ai_fire = unpack_int_value (en, INT_TYPE_SUPPRESS_AI_FIRE); raw->invulnerable_from_collisions = unpack_int_value (en, INT_TYPE_INVULNERABLE_FROM_COLLISIONS); raw->invulnerable_from_weapons = unpack_int_value (en, INT_TYPE_INVULNERABLE_FROM_WEAPONS); raw->cheats_enabled = unpack_int_value (en, INT_TYPE_CHEATS_ENABLED); raw->skip_night_time = unpack_int_value (en, INT_TYPE_SKIP_NIGHT_TIME); raw->weather_increasing = unpack_int_value (en, INT_TYPE_WEATHER_INCREASING); raw->wind_increasing = unpack_int_value (en, INT_TYPE_WIND_INCREASING); raw->local_weather_model = unpack_int_value (en, INT_TYPE_LOCAL_WEATHER_MODEL); // // link into system // // // need to insert session into update list after camera entity // ASSERT (get_camera_entity ()); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), get_camera_entity ()); set_session_entity (en); set_display_campaign_timer_valid (FALSE); break; } //////////////////////////////////////// case PACK_MODE_BROWSE_SESSION: //////////////////////////////////////// { // // create entity // ASSERT (!get_session_entity ()); index = unpack_entity_safe_index (); en = get_free_entity (index); set_local_entity_type (en, ENTITY_TYPE_SESSION); raw = (session *) malloc_fast_mem (sizeof (session)); set_local_entity_data (en, raw); memset (raw, 0, sizeof (session)); // // unpack data (in exactly the same order as the data was packed) // raw->version_number = unpack_int_value (en, INT_TYPE_VERSION_NUMBER); unpack_list_root (en, LIST_TYPE_FORCE, &raw->force_root); // update_link // tour of duty time raw->elapsed_time = unpack_float_value (en, FLOAT_TYPE_ELAPSED_TIME); raw->start_time = unpack_float_value (en, FLOAT_TYPE_START_TIME); // time_of_day_resync // time_of_day_acceleration // weather radius // weather_mode_transitional_period // weather_mode_transitional_status raw->weather_mode = (weathermodes) unpack_int_value (en, INT_TYPE_WEATHER_MODE); // target_weather_mode // weather position // weather velocity raw->day_segment_type = (day_segment_types) unpack_int_value (en, INT_TYPE_DAY_SEGMENT_TYPE); raw->population_x_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MIN); raw->population_x_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_X_MAX); raw->population_z_min = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MIN); raw->population_z_max = unpack_float_value (en, FLOAT_TYPE_POPULATION_Z_MAX); raw->campaign_requires_apache_havoc = unpack_int_value (en, INT_TYPE_CAMPAIGN_REQUIRES_APACHE_HAVOC); // infinite_weapons // skip_night_time // weather increasing set_session_entity (en); break; } } }
void set_reverse_tactical_camera_values (entity *source, entity *target) { camera *raw; int airborne; object_3d_index_numbers object_3d_index; object_3d_bounds *bounding_box; float length, radius, z_min, z_max, rad_alt, dx, dy, dz; vec3d source_position, target_position, direction; ASSERT (source); ASSERT (target); ASSERT (get_camera_entity ()); raw = get_local_entity_data (get_camera_entity ()); // // get camera position // if (get_local_entity_int_value (target, INT_TYPE_IDENTIFY_FIXED)) { object_3d_index = get_local_entity_int_value (target, INT_TYPE_OBJECT_3D_SHAPE); bounding_box = get_object_3d_bounding_box (object_3d_index); dx = bounding_box->xmax - bounding_box->xmin; dy = bounding_box->ymax; dz = bounding_box->zmax - bounding_box->zmin; radius = sqrt ((dx * dx) + (dy * dy) + (dz * dz)) * 2.0; } else { z_min = get_local_entity_float_value (target, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE); z_max = get_local_entity_float_value (target, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE); ASSERT (z_min < z_max); radius = ((z_max - z_min) * 0.05) + z_min; } get_local_entity_target_point (source, &source_position); get_local_entity_target_point (target, &target_position); airborne = FALSE; if (get_local_entity_int_value (target, INT_TYPE_AIRBORNE_AIRCRAFT)) { if (point_inside_map_area (&target_position)) { rad_alt = max (target_position.y - get_3d_terrain_elevation (target_position.x, target_position.z), 0.0); if (rad_alt > z_min) { airborne = TRUE; } } } if (airborne) { direction.x = target_position.x - source_position.x; direction.y = target_position.y - source_position.y; direction.z = target_position.z - source_position.z; length = (direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&direction, length); } else { direction.x = 0.0; direction.y = 0.0; direction.z = -1.0; } } else { direction.x = target_position.x - source_position.x; direction.y = 0.0; direction.z = target_position.z - source_position.z; length = (direction.x * direction.x) + (direction.z * direction.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&direction, length); } else { direction.x = 0.0; direction.z = -1.0; } direction.y = 0.5; normalise_3d_vector (&direction); } raw->position.x = target_position.x + (direction.x * radius); raw->position.y = target_position.y + (direction.y * radius); raw->position.z = target_position.z + (direction.z * radius); // // keep point above ground (unless point off map) // if (point_inside_map_area (&raw->position)) { raw->position.y = max (raw->position.y, get_3d_terrain_point_data (raw->position.x, raw->position.z, &raw->terrain_info) + CAMERA_MIN_HEIGHT_ABOVE_GROUND); } // // get camera attitude // direction.x = target_position.x - raw->position.x; direction.y = target_position.y - raw->position.y; direction.z = target_position.z - raw->position.z; length = (direction.x * direction.x) + (direction.y * direction.y) + (direction.z * direction.z); if (length > 1.0) { length = sqrt (length); normalise_3d_vector_given_magnitude (&direction, length); get_matrix3x3_from_unit_vec3d (raw->attitude, &direction); } else { get_identity_matrix3x3 (raw->attitude); } // // motion vector // get_local_entity_vec3d (target, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector); }
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); }
static entity *create_local (entity_types type, int index, char *pargs) { entity *en; fixed_wing *raw; entity_sub_types group_sub_type; //////////////////////////////////////// // // 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) { //////////////////////////////////////// // // MALLOC ENTITY DATA // //////////////////////////////////////// set_local_entity_type (en, type); raw = malloc_fast_mem (sizeof (fixed_wing)); 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 (fixed_wing)); // // mobile // raw->ac.mob.sub_type = ENTITY_SUB_TYPE_UNINITIALISED; raw->ac.mob.position.x = MID_MAP_X; raw->ac.mob.position.y = MID_MAP_Y; raw->ac.mob.position.z = MID_MAP_Z; get_identity_matrix3x3 (raw->ac.mob.attitude); raw->ac.mob.alive = TRUE; raw->ac.mob.side = ENTITY_SIDE_UNINITIALISED; raw->ac.operational_state = OPERATIONAL_STATE_UNKNOWN; // // aircraft // raw->ac.object_3d_shape = OBJECT_3D_INVALID_OBJECT_INDEX; raw->ac.weapon_config_type = WEAPON_CONFIG_TYPE_UNINITIALISED; raw->ac.selected_weapon = ENTITY_SUB_TYPE_WEAPON_NO_WEAPON; raw->ac.weapon_vector.x = 0.0; raw->ac.weapon_vector.y = 0.0; raw->ac.weapon_vector.z = 1.0; raw->ac.weapon_to_target_vector.x = 0.0; raw->ac.weapon_to_target_vector.y = 0.0; raw->ac.weapon_to_target_vector.z = -1.0; raw->ac.loading_door_state = AIRCRAFT_LOADING_DOORS_OPEN_FLOAT_VALUE; raw->ac.undercarriage_state = AIRCRAFT_UNDERCARRIAGE_DOWN_FLOAT_VALUE; raw->ac.air_radar_contact_timeout = AIR_RADAR_CONTACT_TIMEOUT_INVALID; // // fixed_wing // //////////////////////////////////////// // // OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES // //////////////////////////////////////// set_local_entity_attributes (en, pargs); //////////////////////////////////////// // // CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN // //////////////////////////////////////// ASSERT (raw->ac.member_link.parent); ASSERT (get_local_entity_type (raw->ac.member_link.parent) == ENTITY_TYPE_GROUP); //////////////////////////////////////// // // RESOLVE DEFAULT VALUES // //////////////////////////////////////// // // side // if (raw->ac.mob.side == ENTITY_SIDE_UNINITIALISED) { raw->ac.mob.side = get_local_entity_int_value (raw->ac.member_link.parent, INT_TYPE_SIDE); } ASSERT (raw->ac.mob.side != ENTITY_SIDE_NEUTRAL); // // sub_type // if (raw->ac.mob.sub_type == ENTITY_SUB_TYPE_UNINITIALISED) { group_sub_type = get_local_entity_int_value (raw->ac.member_link.parent, INT_TYPE_ENTITY_SUB_TYPE); if (raw->ac.mob.side == ENTITY_SIDE_BLUE_FORCE) { raw->ac.mob.sub_type = group_database[group_sub_type].default_blue_force_sub_type; } else { raw->ac.mob.sub_type = group_database[group_sub_type].default_red_force_sub_type; } } ASSERT (entity_sub_type_aircraft_valid (raw->ac.mob.sub_type)); // // 3D shape // if (raw->ac.object_3d_shape == OBJECT_3D_INVALID_OBJECT_INDEX) { raw->ac.object_3d_shape = aircraft_database[raw->ac.mob.sub_type].default_3d_shape; } // // weapon config // if (raw->ac.weapon_config_type == WEAPON_CONFIG_TYPE_UNINITIALISED) { raw->ac.weapon_config_type = aircraft_database[raw->ac.mob.sub_type].default_weapon_config_type; } ASSERT (weapon_config_type_valid (raw->ac.weapon_config_type)); // // damage levels // raw->ac.damage_level = aircraft_database[raw->ac.mob.sub_type].initial_damage_level; //////////////////////////////////////// // // BUILD COMPONENTS // //////////////////////////////////////// // // 3D object // raw->ac.inst3d = construct_3d_object (raw->ac.object_3d_shape); set_fixed_wing_id_number (en); initialise_fixed_wing_propellors (en); #if RECOGNITION_GUIDE raw->ac.loading_door_state = AIRCRAFT_LOADING_DOORS_CLOSED_FLOAT_VALUE; #endif // // weapon config // raw->ac.weapon_package_status_array = malloc_fast_mem (SIZE_WEAPON_PACKAGE_STATUS_ARRAY); memset (raw->ac.weapon_package_status_array, 0, SIZE_WEAPON_PACKAGE_STATUS_ARRAY); load_local_entity_weapon_config (en); // // update force info // add_to_force_info (get_local_force_entity (raw->ac.mob.side), en); //////////////////////////////////////// // // LINK INTO SYSTEM // //////////////////////////////////////// insert_local_entity_into_parents_child_list (en, LIST_TYPE_MEMBER, raw->ac.member_link.parent, raw->ac.member_link.child_pred); // // insert into LIST_TYPE_MEMBER before LIST_TYPE_VIEW // insert_local_entity_into_parents_child_list (en, LIST_TYPE_VIEW, get_camera_entity (), get_local_entity_view_list_pred (en)); insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, get_local_sector_entity (&raw->ac.mob.position), NULL); insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL); } return (en); }