void update_vector_acceleration_dynamics (void) { vec3d position; get_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &position); current_flight_dynamics->position.x = position.x; current_flight_dynamics->position.y = position.y; current_flight_dynamics->position.z = position.z; // convert to world axis and // move the object current_flight_dynamics->world_velocity_x.value = (current_flight_dynamics->velocity_x.value * cos (current_flight_dynamics->heading.value)) + (current_flight_dynamics->velocity_z.value * sin (current_flight_dynamics->heading.value)) + (current_flight_dynamics->velocity_y.value * sin (current_flight_dynamics->pitch.value) * sin (current_flight_dynamics->heading.value)); current_flight_dynamics->world_velocity_y.value = (current_flight_dynamics->velocity_y.value) + (current_flight_dynamics->velocity_z.value * sin (current_flight_dynamics->pitch.value)) + (current_flight_dynamics->velocity_x.value * sin (current_flight_dynamics->roll.value)); current_flight_dynamics->world_velocity_z.value = (current_flight_dynamics->velocity_z.value * cos (current_flight_dynamics->heading.value)) + (current_flight_dynamics->velocity_x.value * sin (current_flight_dynamics->heading.value)) + (current_flight_dynamics->velocity_y.value * sin (current_flight_dynamics->pitch.value) * cos (current_flight_dynamics->heading.value)); current_flight_dynamics->position.x += current_flight_dynamics->world_velocity_x.value * get_delta_time (); current_flight_dynamics->position.y += current_flight_dynamics->world_velocity_y.value * get_delta_time (); current_flight_dynamics->position.z += current_flight_dynamics->world_velocity_z.value * get_delta_time (); // maintain motion vector for outputed variables. current_flight_dynamics->model_motion_vector.x = current_flight_dynamics->velocity_x.value; current_flight_dynamics->model_motion_vector.y = current_flight_dynamics->velocity_y.value; current_flight_dynamics->model_motion_vector.z = current_flight_dynamics->velocity_z.value; current_flight_dynamics->world_motion_vector.x = current_flight_dynamics->world_velocity_x.value; current_flight_dynamics->world_motion_vector.y = current_flight_dynamics->world_velocity_y.value; current_flight_dynamics->world_motion_vector.z = current_flight_dynamics->world_velocity_z.value; position.x = current_flight_dynamics->position.x; position.y = current_flight_dynamics->position.y; position.z = current_flight_dynamics->position.z; set_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &position); }
void update_vector_altitude_dynamics (void) { static float last_ground_height = 0; matrix3x3 attitude; float heading, pitch, roll, ground_height, centre_of_gravity_to_ground_distance; vec3d position, *face_normal; centre_of_gravity_to_ground_distance = get_local_entity_float_value (get_gunship_entity (), FLOAT_TYPE_CENTRE_OF_GRAVITY_TO_GROUND_DISTANCE); get_local_entity_attitude_matrix (get_gunship_entity (), attitude); ground_height = get_local_entity_float_value (get_gunship_entity (), FLOAT_TYPE_TERRAIN_ELEVATION); // // debug // if ((ground_height < -1000) || (ground_height > 32000)) { debug_log ("!!!!!!!!!!!!!! GROUND HEIGHT %f", ground_height); ground_height = last_ground_height; } // // end // last_ground_height = ground_height; current_flight_dynamics->altitude.value = current_flight_dynamics->position.y; current_flight_dynamics->altitude.min = ground_height; switch (get_local_entity_int_value (get_gunship_entity (), INT_TYPE_OPERATIONAL_STATE)) { case OPERATIONAL_STATE_LANDED: { if (current_flight_dynamics->world_velocity_y.value > 0.0) { #if DEBUG_DYNAMICS debug_log ("VECTOR DYN: takeoff !"); #endif set_local_entity_int_value (get_gunship_entity (), INT_TYPE_OPERATIONAL_STATE, OPERATIONAL_STATE_NAVIGATING); delete_local_entity_from_parents_child_list (get_gunship_entity (), LIST_TYPE_CURRENT_WAYPOINT); transmit_entity_comms_message (ENTITY_COMMS_MOBILE_TAKEOFF, get_gunship_entity ()); } else { entity *wp; vec3d wp_pos; wp = get_local_entity_parent (get_gunship_entity (), LIST_TYPE_CURRENT_WAYPOINT); if (wp) { get_local_waypoint_formation_position (get_local_entity_int_value (get_gunship_entity (), INT_TYPE_FORMATION_POSITION), wp, &wp_pos); ground_height = wp_pos.y; } current_flight_dynamics->world_velocity_y.value = max (current_flight_dynamics->world_velocity_y.value, 0.0); current_flight_dynamics->velocity_y.value = max (current_flight_dynamics->velocity_y.value, 0.0); memset (¤t_flight_dynamics->world_motion_vector, 0, sizeof (vec3d)); current_flight_dynamics->velocity_x.value = bound (current_flight_dynamics->velocity_x.value, knots_to_metres_per_second (-10), knots_to_metres_per_second (50)); current_flight_dynamics->velocity_y.value = 0; current_flight_dynamics->velocity_z.value = bound (current_flight_dynamics->velocity_z.value, knots_to_metres_per_second (-10), knots_to_metres_per_second (50)); current_flight_dynamics->position.y = ground_height + centre_of_gravity_to_ground_distance; current_flight_dynamics->altitude.value = ground_height + centre_of_gravity_to_ground_distance; heading = get_heading_from_attitude_matrix (attitude); //get_3d_terrain_face_normal (&n, current_flight_dynamics->position.x, current_flight_dynamics->position.z); face_normal = get_local_entity_ptr_value (get_gunship_entity (), PTR_TYPE_TERRAIN_FACE_NORMAL); get_3d_transformation_matrix_from_face_normal_and_heading (attitude, face_normal, heading); pitch = get_pitch_from_attitude_matrix (attitude); pitch += rad (aircraft_database [ENTITY_SUB_TYPE_AIRCRAFT_AH64D_APACHE_LONGBOW].fuselage_angle); roll = get_roll_from_attitude_matrix (attitude); get_3d_transformation_matrix (attitude, heading, pitch, roll); position.x = current_flight_dynamics->position.x; position.y = current_flight_dynamics->position.y; position.z = current_flight_dynamics->position.z; set_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &position); set_local_entity_attitude_matrix (get_gunship_entity (), attitude); } break; } default: { if (current_flight_dynamics->world_velocity_y.value < 0.0) { if (current_flight_dynamics->altitude.value < current_flight_dynamics->altitude.min + centre_of_gravity_to_ground_distance) { if (get_local_entity_int_value (get_gunship_entity (), INT_TYPE_OPERATIONAL_STATE) != OPERATIONAL_STATE_LANDED) { // // need to find what wp the user is trying to land on .... // //entity //*wp; #if DEBUG_DYNAMICS debug_log ("VECTOR DYN: landed !"); #endif set_local_entity_int_value (get_gunship_entity (), INT_TYPE_OPERATIONAL_STATE, OPERATIONAL_STATE_LANDED); //transmit_entity_comms_message (ENTITY_COMMS_MOBILE_LAND, get_gunship_entity (), wp); } } } break; } } current_flight_dynamics->altitude.value = bound ( current_flight_dynamics->altitude.value, current_flight_dynamics->altitude.min, current_flight_dynamics->altitude.max); }
void interpolate_entity_position (entity *en) { vec3d new_position, *motion_vector, *position; connection_list_type *connection; float delta_time; if ((!command_line_comms_interpolate_gunships) || (get_local_entity_int_value (en, INT_TYPE_LANDED))) { return; } position = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION); motion_vector = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_MOTION_VECTOR); if (get_comms_model () == COMMS_MODEL_CLIENT) { connection = get_connection_list_item (get_server_id ()); } else { connection = get_gunships_connection_list_item (en); } if (connection) { delta_time = (float) (get_system_time () - connection->interpolation_time) / TIME_1_SECOND; new_position.x = position->x + motion_vector->x * delta_time; new_position.y = position->y + motion_vector->y * delta_time; new_position.z = position->z + motion_vector->z * delta_time; set_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &new_position); if (get_comms_model () == COMMS_MODEL_SERVER) { connection->interpolation_time = get_system_time (); } #if DEBUG_MODULE debug_log ("SERVER: interpolating entity %s (%d) old [%f, %f, %f], new [%f, %f, %f], motion_vector [%f, %f, %f], deltatime %f", get_local_entity_string (en, STRING_TYPE_FULL_NAME), get_local_entity_index (en), position->x, position->y, position->z, new_position.x, new_position.y, new_position.z, motion_vector->x, motion_vector->y, motion_vector->z, delta_time); #endif } }
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; } } }
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; } } }
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); } } }
void ship_vehicle_movement (entity *en) { ship_vehicle *raw; entity *guide, *current_waypoint; vec3d wp_pos, wp_vec, new_pos; float roll, pitch, heading, sqr_range, turn_rate, required_heading, delta_heading, current_velocity, new_velocity; raw = get_local_entity_data (en); // // abort if mobile is not moving (i.e. landed, or dead) // if (!get_local_entity_int_value (en, INT_TYPE_MOBILE_MOVING)) { return; } // // abort if the mobile has no PRIMARY guide (also stops ships from moving if just engaging) // guide = get_local_entity_primary_guide (en); if (!guide) { return; } current_waypoint = get_local_entity_parent (guide, LIST_TYPE_CURRENT_WAYPOINT); ASSERT (current_waypoint); current_velocity = raw->vh.mob.velocity; // // GET WAYPOINT POSITION // ship_movement_get_waypoint_position (en, &wp_pos); wp_vec.x = wp_pos.x - raw->vh.mob.position.x; wp_vec.y = 0; wp_vec.z = wp_pos.z - raw->vh.mob.position.z; sqr_range = ((wp_vec.x * wp_vec.x) + (wp_vec.z * wp_vec.z)); #if DEBUG_MODULE create_vectored_debug_3d_object (&wp_pos, (vec3d *) &raw->vh.mob.attitude [1], OBJECT_3D_RED_ARROW, 0, 0.20); #endif // ???? if (fabs (sqr_range) < 1 * CENTIMETRE) { wp_vec.z = 0; wp_vec.y = 0; wp_vec.z = 1; } //////////////////////////////////////// // // angles // //////////////////////////////////////// // heading normalise_3d_vector (&wp_vec); heading = get_heading_from_attitude_matrix (raw->vh.mob.attitude); required_heading = atan2 (wp_vec.x, wp_vec.z); { float angle, range, v; range = sqrt (sqr_range); v = sqrt (0.5 * range * vehicle_database [raw->vh.mob.sub_type].g_max); angle = ((raw->vh.mob.attitude [2][0] * wp_vec.x) + (raw->vh.mob.attitude [2][2] * wp_vec.z)); if (angle < 0.707) // 45 degs. { // wp behind ship #if DEBUG_MODULE debug_log ("SH_MOVE: ship cannot reach wp at vel %f m/s (max v %f), range %f, g %f", raw->vh.mob.velocity, v, range, vehicle_database [raw->vh.mob.sub_type].g_max); #endif new_velocity = bound (v, 0.0, get_local_entity_float_value (guide, FLOAT_TYPE_VELOCITY)); } else { #if DEBUG_MODULE debug_log ("SH_MOVE: ship can reach wp at vel %f m/s (max v %f), range %f, g %f", raw->vh.mob.velocity, v, range, vehicle_database [raw->vh.mob.sub_type].g_max); #endif new_velocity = get_local_entity_float_value (guide, FLOAT_TYPE_VELOCITY); } } turn_rate = 0.0; if (raw->vh.mob.velocity != 0.0) { turn_rate = fabs (vehicle_database [raw->vh.mob.sub_type].g_max / raw->vh.mob.velocity); } delta_heading = required_heading - heading; if (delta_heading <= -PI) { delta_heading += PI2; } if (delta_heading >= PI) { delta_heading -= PI2; } delta_heading = bound (delta_heading, -turn_rate, turn_rate); heading += delta_heading * get_entity_movement_delta_time (); pitch = 0.0; roll = 0.0; //////////////////////////////////////// // // attitude // //////////////////////////////////////// get_3d_transformation_matrix (raw->vh.mob.attitude, heading, rad (pitch), rad (roll)); //////////////////////////////////////// // // velocity // //////////////////////////////////////// { float maximum_acceleration, required_acceleration; required_acceleration = (new_velocity - raw->vh.mob.velocity); maximum_acceleration = get_local_entity_float_value (en, FLOAT_TYPE_MAX_ACCELERATION); raw->vh.mob.velocity += min (required_acceleration, maximum_acceleration) * get_entity_movement_delta_time (); } //////////////////////////////////////// // // position // //////////////////////////////////////// new_pos.x = raw->vh.mob.position.x + (raw->vh.mob.velocity * raw->vh.mob.zv.x * get_entity_movement_delta_time ()); new_pos.y = 0.0; new_pos.z = raw->vh.mob.position.z + (raw->vh.mob.velocity * raw->vh.mob.zv.z * get_entity_movement_delta_time ()); bound_position_to_map_volume (&new_pos); // // Calculate motion vector for view system // raw->vh.mob.motion_vector.x = (new_pos.x - raw->vh.mob.position.x) * get_one_over_delta_time (); raw->vh.mob.motion_vector.y = 0.0; raw->vh.mob.motion_vector.z = (new_pos.z - raw->vh.mob.position.z) * get_one_over_delta_time (); new_pos.y = 0.0; set_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &new_pos); }