Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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 (&current_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);
}
Ejemplo n.º 3
0
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
	}
}
Ejemplo n.º 4
0
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;
		}
	}
}
Ejemplo n.º 5
0
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;
		}
	}
}
Ejemplo n.º 6
0
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);
		}
	}
}
Ejemplo n.º 7
0
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);
}