Example #1
0
static void update_recognition_guide_camera (camera *raw, object_3d_camera_index_numbers index)
{
	entity
		*en;

	object_3d_instance
		*inst3d;

	viewpoint
		vp;

	//
	// pre-amble
	//

	ASSERT (raw);

	ASSERT (raw->external_view_entity);

	en = raw->external_view_entity;

	//
	// get camera position and attitude
	//

	inst3d = (object_3d_instance *) get_local_entity_ptr_value (en, PTR_TYPE_INSTANCE_3D_OBJECT);

	ASSERT (inst3d);

	set_3d_exclusive_instance ( inst3d );

	get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &inst3d->vp.position);

	get_local_entity_attitude_matrix (en, inst3d->vp.attitude);

	get_object_3d_camera_position (inst3d, index, 0, 0.0, &vp);

	raw->position = vp.position;

	memcpy (raw->attitude, vp.attitude, sizeof (matrix3x3));

	//
	// 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) + 0.5f);
	}

	//
	// motion vector
	//

	get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector);
}
Example #2
0
void set_hud_bob_up_overlay (void)
{
	hud_bob_up_overlay = TRUE;

	hud_bob_up_heading = get_local_entity_float_value (get_gunship_entity (), FLOAT_TYPE_HEADING);

	get_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &hud_bob_up_position);
}
Example #3
0
void update_overview_camera (camera *raw)
{
	entity
		*en;

	vec3d
		rel_camera_position;

	//
	// pre-amble
	//

	ASSERT (raw);

	ASSERT (raw->external_view_entity);

	en = raw->external_view_entity;

	//
	// get camera attitude
	//

	get_3d_transformation_matrix (raw->attitude, get_local_entity_float_value (en, FLOAT_TYPE_HEADING) + rad (180.0), rad (-15.0), 0.0);

	//
	// get camera position
	//

	rel_camera_position.x = 0.0;
	rel_camera_position.y = 0.0;
	rel_camera_position.z = -get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE);

	multiply_matrix3x3_vec3d (&rel_camera_position, raw->attitude, &rel_camera_position);

	get_local_entity_target_point (en, &raw->position);

	raw->position.x += rel_camera_position.x;
	raw->position.y += rel_camera_position.y;
	raw->position.z += rel_camera_position.z;

	//
	// 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) + 0.5f);
	}

	//
	// motion vector
	//

	get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector);
}
Example #4
0
entity *get_closest_mobile_entity (vec3d *pos)
{

	entity
		*closest_en = NULL,
		*en;

	int
		range,
		best_range = INT_MAX;

	vec3d
		pos2,
		test_pos;

	en = get_local_entity_list ();

	while (en)
	{

		if (get_local_entity_int_value (en, INT_TYPE_IDENTIFY_MOBILE))
		{
	
			get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &pos2);
	
			test_pos.x = pos->x - pos2.x;
	
			test_pos.y = 0.0;
	
			test_pos.z = pos->z - pos2.z;
	
			range = get_3d_vector_magnitude (&test_pos);
	
			if (range < best_range)
			{
	
				best_range = range;
	
				closest_en = en;
	
				if (range < 1.0)
				{
				
					return closest_en;
				}
			}
		}

		en = get_local_entity_succ (en);
	}
	
	return closest_en;
}
Example #5
0
void reset_chase_camera (camera *raw)
{
	ASSERT (raw);

	ASSERT (raw->external_view_entity);

	//
	// motion vector
	//

	get_local_entity_vec3d (raw->external_view_entity, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector);
}
Example #6
0
void get_comanche_eo_relative_centred_viewpoint (viewpoint *vp)
{
	entity
		*source;

	object_3d_instance
		*inst3d;

	object_3d_sub_object_search_data
		search;

	ASSERT (vp);

	source = get_gunship_entity ();

	inst3d = (object_3d_instance *) get_local_entity_ptr_value (source, PTR_TYPE_INSTANCE_3D_OBJECT);

	ASSERT (inst3d);

	inst3d->vp.x = 0.0;
	inst3d->vp.y = 0.0;
	inst3d->vp.z = 0.0;

	get_local_entity_attitude_matrix (source, inst3d->vp.attitude);

	search.search_depth = 0;
	search.search_object = inst3d;
	search.sub_object_index = OBJECT_3D_SUB_OBJECT_COMANCHE_EO_CAMERA;

	if (find_object_3d_sub_object (&search) == SUB_OBJECT_SEARCH_RESULT_OBJECT_FOUND)
	{
		get_3d_sub_object_world_viewpoint (search.result_sub_object, vp);
	}
	else
	{
		//
		// can happpen if the object is being destroyed
		//

		memcpy (&vp->position, &inst3d->vp.position, sizeof (vec3d));

		debug_log ("OBJECT_3D_SUB_OBJECT_COMANCHE_EO_CAMERA missing from Comanche");
	}

	memcpy (&vp->attitude, &inst3d->vp.attitude, sizeof (matrix3x3));

	//
	// fix up the instance position (just in case)
	//

	get_local_entity_vec3d (source, VEC3D_TYPE_POSITION, &inst3d->vp.position);
}
Example #7
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);
}
Example #8
0
void get_default_crew_viewpoint (int index, object_3d_instance   *virtual_cockpit_inst3d)
{
	viewpoint
		vp;

	float
		head_pitch_datum;

	head_pitch_datum = pilot_head_pitch_datum;

	//
	// rotate head
	//

	virtual_cockpit_inst3d->sub_objects[index].relative_heading = -pilot_head_heading;
	virtual_cockpit_inst3d->sub_objects[index].relative_pitch = head_pitch_datum - pilot_head_pitch;
	virtual_cockpit_inst3d->sub_objects[index].relative_roll = 0.0;

	//
	// get viewpoint (avoid jitter)
	//

	virtual_cockpit_inst3d->vp.x = 0.0;
	virtual_cockpit_inst3d->vp.y = 0.0;
	virtual_cockpit_inst3d->vp.z = 0.0;

	get_local_entity_attitude_matrix (get_gunship_entity (), virtual_cockpit_inst3d->vp.attitude);

	get_3d_sub_object_world_viewpoint (&virtual_cockpit_inst3d->sub_objects[index], &vp);

	get_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &pilot_head_vp.position);

// x,y,z is here north south east west!
//inserting fixed values here does not work because of head movement

	pilot_head_vp.x += vp.x;
	pilot_head_vp.y += vp.y;
	pilot_head_vp.z += vp.z;

	memcpy (pilot_head_vp.attitude, vp.attitude, sizeof (matrix3x3));

	vp.x = -vp.x;
	vp.y = -vp.y;
	vp.z = -vp.z;

	multiply_transpose_matrix3x3_vec3d (&virtual_cockpit_inst3d->vp.position, pilot_head_vp.attitude, &vp.position);


}
Example #9
0
void get_ah64a_eo_centred_viewpoint (viewpoint *vp)
{
	entity
		*source;

	object_3d_instance
		*inst3d;

	object_3d_sub_object_search_data
		search;

	ASSERT (vp);

	source = get_gunship_entity ();

	inst3d = (object_3d_instance *) get_local_entity_ptr_value (source, PTR_TYPE_INSTANCE_3D_OBJECT);

	ASSERT (inst3d);

	get_local_entity_vec3d (source, VEC3D_TYPE_POSITION, &inst3d->vp.position);

	get_local_entity_attitude_matrix (source, inst3d->vp.attitude);

	search.search_depth = 0;
	search.search_object = inst3d;
	search.sub_object_index = OBJECT_3D_SUB_OBJECT_AH64D_TADS_HEADING;

	if (find_object_3d_sub_object (&search) == SUB_OBJECT_SEARCH_RESULT_OBJECT_FOUND)
	{
		get_3d_sub_object_world_viewpoint (search.result_sub_object, vp);
	}
	else
	{
		//
		// can happpen if the object is being destroyed
		//

		memcpy (&vp->position, &inst3d->vp.position, sizeof (vec3d));

		debug_log ("OBJECT_3D_SUB_OBJECT_AH64D_TADS_HEADING missing from Apache");
	}

	memcpy (&vp->attitude, &inst3d->vp.attitude, sizeof (matrix3x3));
}
Example #10
0
static void reset_recognition_guide_camera (camera *raw)
{
	entity
		*en;

	//
	// pre-amble
	//

	ASSERT (raw);

	ASSERT (raw->external_view_entity);

	en = raw->external_view_entity;

	//
	// motion vector
	//

	get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector);
}
Example #11
0
void set_vector_dynamics_defaults (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;

	get_identity_matrix3x3 (current_flight_dynamics->attitude);

	current_flight_dynamics->air_density.value = 2.3;
	current_flight_dynamics->air_density.max = 2.3;
	current_flight_dynamics->air_density.min = 1.5;

	current_flight_dynamics->altitude.min = 0.0;
	current_flight_dynamics->altitude.max = MAX_MAP_Y;

	current_flight_dynamics->input_data.cyclic_x.min = -100.0;
	current_flight_dynamics->input_data.cyclic_x.max = 100.0;

	current_flight_dynamics->input_data.cyclic_y.min = -100.0;
	current_flight_dynamics->input_data.cyclic_y.max = 100.0;

	current_flight_dynamics->input_data.cyclic_horizontal_pressure.min = -100.0;
	current_flight_dynamics->input_data.cyclic_horizontal_pressure.max = 100.0;

	current_flight_dynamics->input_data.cyclic_vertical_pressure.min = -100.0;
	current_flight_dynamics->input_data.cyclic_vertical_pressure.max = 100.0;

	current_flight_dynamics->input_data.collective_pressure.min = -10.0;
	current_flight_dynamics->input_data.collective_pressure.max = 10.0;

	current_flight_dynamics->input_data.pedal.min = -100.0;
	current_flight_dynamics->input_data.pedal.max = 100.0;

	current_flight_dynamics->input_data.pedal_pressure.min = -10.0;
	current_flight_dynamics->input_data.pedal_pressure.max = 10.0;

	// main rotor characteristics

	current_flight_dynamics->main_rotor_diameter.value = 14.63;
	current_flight_dynamics->main_rotor_area.value = PI * pow ((current_flight_dynamics->main_rotor_diameter.value / 2.0), 2);

	current_flight_dynamics->main_rotor_induced_air.value = 4.63;
	current_flight_dynamics->main_rotor_induced_air.min = 2.5;
	current_flight_dynamics->main_rotor_induced_air.max = 6.5;

	current_flight_dynamics->main_rotor_roll_angle.min = rad (-5.0);
	current_flight_dynamics->main_rotor_roll_angle.max = rad (5.0);

	current_flight_dynamics->main_rotor_pitch_angle.min = rad (-5.0);
	current_flight_dynamics->main_rotor_pitch_angle.max = rad (5.0);

	current_flight_dynamics->main_rotor_thrust.min = 0.0;
	current_flight_dynamics->main_rotor_thrust.max = 100.0;

	current_flight_dynamics->main_rotor_rpm.value = 80.0;
	current_flight_dynamics->main_rotor_rpm.min = 80.0;
	current_flight_dynamics->main_rotor_rpm.max = 100.0;

	current_flight_dynamics->main_rotor_coning_angle.min = rad (-3.0);
	current_flight_dynamics->main_rotor_coning_angle.max = rad (10.0);

	current_flight_dynamics->main_blade_pitch.value = 2.5;
	current_flight_dynamics->main_blade_pitch.min = rad (2.5);
	current_flight_dynamics->main_blade_pitch.max = rad (6.0);

	// tail rotor characteristics

	current_flight_dynamics->tail_rotor_diameter.value = 2.79;

	current_flight_dynamics->tail_rotor_rpm.value = 80.0;
	current_flight_dynamics->tail_rotor_rpm.min = 80.0;
	current_flight_dynamics->tail_rotor_rpm.max = 100.0;

	current_flight_dynamics->tail_rotor_thrust.min = 0.0;
	current_flight_dynamics->tail_rotor_thrust.max = 100.0;

	current_flight_dynamics->tail_blade_pitch.value = 0.0;
	current_flight_dynamics->tail_blade_pitch.min = rad (-5.0);
	current_flight_dynamics->tail_blade_pitch.max = rad (5.0);

	current_flight_dynamics->tail_boom_length.value = 10.59; // actually the wheelbase (but close enough)

	current_flight_dynamics->cross_coupling_effect.value = 0.0;

	// other

	current_flight_dynamics->velocity_x.min = -11.1;
	current_flight_dynamics->velocity_x.max = 11.1;

	current_flight_dynamics->acceleration_x.min = -10.0;
	current_flight_dynamics->acceleration_x.max = 10.0;

	current_flight_dynamics->velocity_y.value = 0.0;
	current_flight_dynamics->velocity_y.min = -1000.0;
	current_flight_dynamics->velocity_y.max = 15.7;

	current_flight_dynamics->acceleration_y.min = -1000.0;
	current_flight_dynamics->acceleration_y.max = 15.7;

	current_flight_dynamics->velocity_z.min = -8.33;
	current_flight_dynamics->velocity_z.max = knots_to_metres_per_second (250); //(197); // never exceed

	current_flight_dynamics->acceleration_z.value = 0.0;
	current_flight_dynamics->acceleration_z.min = -10.0;
	current_flight_dynamics->acceleration_z.max = 10.0;

	current_flight_dynamics->power_avaliable.min = 0.0;
	current_flight_dynamics->power_avaliable.max = 2530.0;

	current_flight_dynamics->lift.min = -10.0;
	current_flight_dynamics->lift.max = 40.0;


	current_flight_dynamics->drag_x.min = 0.90;
	current_flight_dynamics->drag_x.max = 0.98;

	current_flight_dynamics->drag_y.min = 0.80;
	current_flight_dynamics->drag_y.max = 0.97;

	current_flight_dynamics->drag_z.min = 0.9999;
	current_flight_dynamics->drag_z.max = 1.0;

	current_flight_dynamics->heading_inertia.value = 2000;
	current_flight_dynamics->pitch_inertia.value = 1200;
	current_flight_dynamics->roll_inertia.value = 1200;

	current_flight_dynamics->mass.value = 7480.0;
	current_flight_dynamics->mass.min = 5000.0;
	current_flight_dynamics->mass.max = 10000.0;

	current_flight_dynamics->centre_of_gravity.x = 0.00;
	current_flight_dynamics->centre_of_gravity.y = 2.475;
	current_flight_dynamics->centre_of_gravity.z = 0.00;
}
Example #12
0
void get_kiowa_crew_viewpoint (void)
{
	object_3d_sub_object_search_data
		search_head,
		search_viewpoint;

	viewpoint
		vp;

	float
		head_pitch_datum;

	//
	// select head
	//

	if (get_local_entity_int_value (get_pilot_entity (), INT_TYPE_CREW_ROLE) == CREW_ROLE_PILOT)
	{
		search_head.sub_object_index = OBJECT_3D_SUB_OBJECT_PILOT_HEAD;

		search_viewpoint.sub_object_index = OBJECT_3D_SUB_OBJECT_PILOT_VIEWPOINT;

		head_pitch_datum = pilot_head_pitch_datum;
	}
	else
	{
		search_head.sub_object_index = OBJECT_3D_SUB_OBJECT_WSO_HEAD;

		search_viewpoint.sub_object_index = OBJECT_3D_SUB_OBJECT_WSO_VIEWPOINT;

		head_pitch_datum = co_pilot_head_pitch_datum;
	}

	//
	// rotate head
	//

	search_head.search_depth = 0;
	search_head.search_object = virtual_cockpit_inst3d;

	if (find_object_3d_sub_object (&search_head) == SUB_OBJECT_SEARCH_RESULT_OBJECT_FOUND)
	{
		search_head.result_sub_object->relative_heading = -pilot_head_heading;
		search_head.result_sub_object->relative_pitch = head_pitch_datum - pilot_head_pitch;

		if ((command_line_TIR_6DOF == TRUE)&&(query_TIR_active() == TRUE))	// Retro 6Feb2005
			search_head.result_sub_object->relative_roll = TIR_GetRoll() / 16383. * PI / 2.;	// Retro 6Feb2005
		else
			search_head.result_sub_object->relative_roll = 0.0;
	}
	else
	{
		debug_fatal ("Failed to locate crew's head in virtual cockpit");
	}

	//
	// get viewpoint (avoid jitter)
	//

	search_viewpoint.search_object = virtual_cockpit_inst3d;
	search_viewpoint.search_depth = 0;

	if (find_object_3d_sub_object (&search_viewpoint) == SUB_OBJECT_SEARCH_RESULT_OBJECT_FOUND)
	{
		virtual_cockpit_inst3d->vp.x = 0.0;
		virtual_cockpit_inst3d->vp.y = 0.0;
		virtual_cockpit_inst3d->vp.z = 0.0;

		get_local_entity_attitude_matrix (get_gunship_entity (), virtual_cockpit_inst3d->vp.attitude);

		get_3d_sub_object_world_viewpoint (search_viewpoint.result_sub_object, &vp);

		get_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &pilot_head_vp.position);

		pilot_head_vp.x += vp.x;
		pilot_head_vp.y += vp.y;
		pilot_head_vp.z += vp.z;

		if ((command_line_TIR_6DOF == TRUE)&&(query_TIR_active() == TRUE))	// Retro 6Feb2005 (whole block)
		{
			matrix3x3 invAttitude;
			vec3d
				shiftVP, shiftWorld;

			// First lets find out the displacement the user wants.. this is in the user's viewsystem coords !!
			// Now store this info in a temp vect3d..
			shiftVP.x = current_custom_cockpit_viewpoint.x;
			shiftVP.y = current_custom_cockpit_viewpoint.y;
			shiftVP.z = current_custom_cockpit_viewpoint.z;

			// Now we need to convert our vec3d into world coords.. for this we need the inverse of the viewpoint attitude matrix..
			get_inverse_matrix (invAttitude, vp.attitude);
			// And rotate ! Voila, the result vec3d is now in world coords..
			multiply_transpose_matrix3x3_vec3d (&shiftWorld, invAttitude, &shiftVP);
			// Now apply that displacement.. BUT ONLY TO THE HEAD !!
			pilot_head_vp.x -= shiftWorld.x;
			pilot_head_vp.y -= shiftWorld.y;
			pilot_head_vp.z -= shiftWorld.z;
		}

		memcpy (pilot_head_vp.attitude, vp.attitude, sizeof (matrix3x3));

		vp.x = -vp.x;
		vp.y = -vp.y;
		vp.z = -vp.z;

		multiply_transpose_matrix3x3_vec3d (&virtual_cockpit_inst3d->vp.position, pilot_head_vp.attitude, &vp.position);

		if ((command_line_TIR_6DOF == TRUE)&&(query_TIR_active() == TRUE))	// Retro 6Feb2005 (whole block)
		{
			// Now shift the viewpoint (AND the model) by the positive displacement.. puts the cockpit back were it belongs..
			// but the viewpoint (the head) is in another place.. fini
			virtual_cockpit_inst3d->vp.x += current_custom_cockpit_viewpoint.x;
			virtual_cockpit_inst3d->vp.y += current_custom_cockpit_viewpoint.y;
			virtual_cockpit_inst3d->vp.z += current_custom_cockpit_viewpoint.z;
		}

	}
	else
	{
		debug_fatal ("Failed to locate crew's viewpoint in virtual cockpit");
	}
}
Example #13
0
void get_kiowa_display_viewpoint (view_modes mode)
{
	object_3d_sub_object_index_numbers
		index;

	object_3d_sub_object_search_data
		search;

	vec3d
		position;

	ASSERT (get_gunship_entity ());

	ASSERT (virtual_cockpit_inst3d);

	switch (mode)
	{
		////////////////////////////////////////
		case VIEW_MODE_VIRTUAL_COCKPIT_PILOT_LHS_DISPLAY:
		////////////////////////////////////////
		{
			index = OBJECT_3D_SUB_OBJECT_COCKPIT_VIEW_MFD_FL;

			break;
		}
		////////////////////////////////////////
		case VIEW_MODE_VIRTUAL_COCKPIT_PILOT_RHS_DISPLAY:
		////////////////////////////////////////
		{
			index = OBJECT_3D_SUB_OBJECT_COCKPIT_VIEW_MFD_FR;

			break;
		}
		////////////////////////////////////////
		case VIEW_MODE_VIRTUAL_COCKPIT_CO_PILOT_LHS_DISPLAY:
		////////////////////////////////////////
		{
			index = OBJECT_3D_SUB_OBJECT_COCKPIT_VIEW_MFD_RL;

			break;
		}
		////////////////////////////////////////
		case VIEW_MODE_VIRTUAL_COCKPIT_CO_PILOT_RHS_DISPLAY:
		////////////////////////////////////////
		{
			index = OBJECT_3D_SUB_OBJECT_COCKPIT_VIEW_MFD_RR;

			break;
		}
		////////////////////////////////////////
		default:
		////////////////////////////////////////
		{
			debug_fatal ("Invalid view mode = %d", mode);

			break;
		}
	}

	virtual_cockpit_inst3d->vp.x = 0.0;
	virtual_cockpit_inst3d->vp.y = 0.0;
	virtual_cockpit_inst3d->vp.z = 0.0;

	////////////////////////////////////////
	//

	#if DEBUG_MODULE_FINE_DISPLAY_CAMERA_POSITION_ADJUSTMENT

	get_identity_matrix3x3 (virtual_cockpit_inst3d->vp.attitude);

	#else

	get_local_entity_attitude_matrix (get_gunship_entity (), virtual_cockpit_inst3d->vp.attitude);

	#endif

	//
	////////////////////////////////////////

	search.search_depth = 0;
	search.search_object = virtual_cockpit_inst3d;
	search.sub_object_index = index;

	if (find_object_3d_sub_object (&search) == SUB_OBJECT_SEARCH_RESULT_OBJECT_FOUND)
	{
		get_3d_sub_object_world_viewpoint (search.result_sub_object, &main_vp);
	}
	else
	{
		debug_fatal ("Failed to locate display viewpoint in virtual cockpit");
	}

	position.x = -main_vp.x;
	position.y = -main_vp.y;
	position.z = -main_vp.z;

	////////////////////////////////////////
	//

	#if DEBUG_MODULE_FINE_DISPLAY_CAMERA_POSITION_ADJUSTMENT
	{
		static float
			z_offset = 0.0;

		float
			dx,
			dy,
			dz;

		if (check_key (DIK_Q))
		{
			z_offset -= 0.0001;
		}

		if (check_key (DIK_A))
		{
			z_offset += 0.0001;
		}

		dx = main_vp.zv.x * z_offset;
		dy = main_vp.zv.y * z_offset;
		dz = main_vp.zv.z * z_offset;

		position.x += dx;
		position.y += dy;
		position.z += dz;

		debug_filtered_log ("offset=%.6f x=%.6f y=%.6f z=%.6f", z_offset, position.x, position.y, position.z);
	}
	#endif

	//
	////////////////////////////////////////

	multiply_transpose_matrix3x3_vec3d (&virtual_cockpit_inst3d->vp.position, main_vp.attitude, &position);

	get_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &position);

	main_vp.x += position.x;
	main_vp.y += position.y;
	main_vp.z += position.z;
}
Example #14
0
void reset_cinematic_camera (camera *raw)
{
	entity
		*en;

	object_3d_instance
		*inst3d;

	int
		num_moving_cameras,
		num_static_cameras,
		attempts;

	//
	// pre-amble
	//

	ASSERT (raw);

	ASSERT (raw->external_view_entity);

	en = raw->external_view_entity;

	inst3d = get_local_entity_ptr_value (en, PTR_TYPE_INSTANCE_3D_OBJECT);

	//
	// select 3D camera
	//

	raw->cinematic_camera_index = OBJECT_3D_INVALID_CAMERA_INDEX;

	if (inst3d)
	{
		num_moving_cameras = get_number_of_3d_object_cameras (inst3d, OBJECT_3D_CAMERA_SCENIC_MOVING);

		num_static_cameras = get_number_of_3d_object_cameras (inst3d, OBJECT_3D_CAMERA_SCENIC_STATIC);

		if ((num_moving_cameras > 0) && (num_static_cameras > 0))
		{
			if (frand1 () < 0.333)
			{
				raw->cinematic_camera_index = OBJECT_3D_CAMERA_SCENIC_MOVING;
			}
			else
			{
				raw->cinematic_camera_index = OBJECT_3D_CAMERA_SCENIC_STATIC;
			}
		}
		else if (num_moving_cameras > 0)
		{
			raw->cinematic_camera_index = OBJECT_3D_CAMERA_SCENIC_MOVING;
		}
		else if (num_static_cameras > 0)
		{
			raw->cinematic_camera_index = OBJECT_3D_CAMERA_SCENIC_STATIC;
		}
	}

	switch (raw->cinematic_camera_index)
	{
		////////////////////////////////////////
		case OBJECT_3D_INVALID_CAMERA_INDEX:
		////////////////////////////////////////
		{
			raw->cinematic_camera_depth = 0;

			raw->cinematic_camera_lifetime = (frand1 () * 2.0) + 2.0;

			raw->cinematic_camera_heading = rad (45.0) * ((float) (rand16 () % 8));

			raw->cinematic_camera_pitch = rad (-45.0) * ((float) (rand16 () % 2));

			#if DEBUG_MODULE

			debug_log
			(
				"CINEMATIC CAMERA is INVALID (object = %s, moving cameras = %d, static cameras = %d, depth = %d, lifetime = %.2f, heading = %.2f, pitch = %.2f)",
				get_local_entity_string (en, STRING_TYPE_FULL_NAME),
				num_moving_cameras,
				num_static_cameras,
		  		raw->cinematic_camera_depth,
				raw->cinematic_camera_lifetime,
				deg (raw->cinematic_camera_heading),
				deg (raw->cinematic_camera_pitch)
			);

			#endif

			break;
		}
		////////////////////////////////////////
		case OBJECT_3D_CAMERA_SCENIC_MOVING:
		////////////////////////////////////////
		{
			//
			// try and prevent using the same moving camera twice in succession
			//

			if (num_moving_cameras > 1)
			{
				attempts = 10;

				while (attempts--)
				{
					raw->cinematic_camera_depth = rand16 () % num_moving_cameras;

					if (raw->cinematic_camera_depth != raw->cinematic_camera_previous_moving_depth)
					{
						break;
					}
				}
			}
			else
			{
				raw->cinematic_camera_depth = 0;
			}

			raw->cinematic_camera_previous_moving_depth = raw->cinematic_camera_depth;

			raw->cinematic_camera_lifetime = get_object_3d_camera_lifetime (inst3d, raw->cinematic_camera_index, raw->cinematic_camera_depth);

			#if DEBUG_MODULE

			debug_log
			(
				"CINEMATIC CAMERA is MOVING (object = %s, moving cameras = %d, static cameras = %d, depth = %d, lifetime = %.2f)",
				get_local_entity_string (en, STRING_TYPE_FULL_NAME),
				num_moving_cameras,
				num_static_cameras,
		  		raw->cinematic_camera_depth,
				raw->cinematic_camera_lifetime
			);

			#endif

			ASSERT (raw->cinematic_camera_lifetime > 0.0);

			break;
		}
		////////////////////////////////////////
		case OBJECT_3D_CAMERA_SCENIC_STATIC:
		////////////////////////////////////////
		{
			//
			// try and prevent using the same static camera twice in succession
			//

			if (num_static_cameras > 1)
			{
				attempts = 10;

				while (attempts--)
				{
					raw->cinematic_camera_depth = rand16 () % num_static_cameras;

					if (raw->cinematic_camera_depth != raw->cinematic_camera_previous_static_depth)
					{
						break;
					}
				}
			}
			else
			{
				raw->cinematic_camera_depth = 0;
			}

			raw->cinematic_camera_previous_static_depth = raw->cinematic_camera_depth;

			raw->cinematic_camera_lifetime = (frand1 () * 2.0) + 2.0;

			#if DEBUG_MODULE

			debug_log
			(
				"CINEMATIC CAMERA is STATIC (object = %s, moving cameras = %d, static cameras = %d, depth = %d, lifetime = %.2f)",
				get_local_entity_string (en, STRING_TYPE_FULL_NAME),
				num_moving_cameras,
				num_static_cameras,
		  		raw->cinematic_camera_depth,
				raw->cinematic_camera_lifetime
			);

			#endif
		}
	}

	raw->cinematic_camera_timer = 0.0;

	//
	// motion vector
	//

	get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector);
}
Example #15
0
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);
}
Example #16
0
aircraft_fire_result aircraft_fire_weapon (entity *en, unsigned int check_flags)
{
	entity
		*target;
	
	aircraft
		*raw;

	vec3d
		*target_pos,
		en_pos;

	ASSERT (en);

	raw = get_local_entity_data (en);

	//
	// Fire suppressed
	//

	if (check_flags & AIRCRAFT_FIRE_SUPPRESSED)
	{
		if (get_local_entity_int_value (get_session_entity (), INT_TYPE_SUPPRESS_AI_FIRE))
		{
			return AIRCRAFT_FIRE_SUPPRESSED;
		}
	}

	//
	// check weapon
	//

	if (check_flags & AIRCRAFT_FIRE_NO_WEAPON)
	{
		if (get_local_entity_int_value (en, INT_TYPE_SELECTED_WEAPON) == ENTITY_SUB_TYPE_WEAPON_NO_WEAPON)
		{
			debug_log ("AC_WPN: Fire Weapon Error - NO WEAPON");
	
			return AIRCRAFT_FIRE_NO_WEAPON;
		}
	}

	//
	// weapon system_ready
	//

	if (check_flags & AIRCRAFT_FIRE_WEAPON_SYSTEM_NOT_READY)
	{
		if (!get_local_entity_int_value (en, INT_TYPE_SELECTED_WEAPON_SYSTEM_READY))
		{
			debug_log ("AC_WPN: Fire Weapon Error - WEAPON SYSTEM NOT READY");
	
			return AIRCRAFT_FIRE_WEAPON_SYSTEM_NOT_READY;
		}
	}

	//
	// find target
	//

	if (check_flags & AIRCRAFT_FIRE_NO_TARGET)
	{
		target = get_local_entity_parent (en, LIST_TYPE_TARGET);
	
		if (!target)
		{
			debug_log ("AC_WPN: Fire Weapon Error - NO TARGET");
	
			return AIRCRAFT_FIRE_NO_TARGET;
		}
	}

	//
	// line of sight checks
	//

	if (check_flags & AIRCRAFT_FIRE_NO_LOS)
	{
		int
			criteria;

		if (get_local_entity_int_value (target, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI)
		{
			criteria = MOBILE_LOS_CHECK_ALL;
		}
		else
		{
			criteria = MOBILE_LOS_CHECK_COURSE_TERRAIN;
		}

		get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &en_pos);

		target_pos = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION);

		en_pos.y -= (get_local_entity_float_value (en, FLOAT_TYPE_CENTRE_OF_GRAVITY_TO_GROUND_DISTANCE) + 2.0);

		if (!check_position_line_of_sight (en, target, &en_pos, target_pos, criteria))
		{
			debug_log ("AC_WPN: Fire Weapon Error - NO LOS (Aircraft %s (%d), Target %s (%d))",
								get_local_entity_string (en, STRING_TYPE_FULL_NAME), get_local_entity_index (en),
								get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target));
	
			return AIRCRAFT_FIRE_NO_LOS;
		}
	}

	//
	// Play Speech
	//

	play_aircraft_weapon_launched_speech (en, raw->selected_weapon);

	//
	// Fire weapon
	//

	launch_client_server_weapon (en, raw->selected_weapon);

	return AIRCRAFT_FIRE_OK;
}
Example #17
0
void update_chase_camera (camera *raw)
{
	entity
		*en;

	float
		combined_heading,
		z_min,
		z_max;

	vec3d
		rel_camera_position;

	//
	// pre-amble
	//

	ASSERT (raw);

	ASSERT (raw->external_view_entity);

	en = raw->external_view_entity;

	//
	// adjust camera heading
	//

	if (adjust_view_left_key || joystick_pov_left)
	{
		raw->chase_camera_heading += CHASE_CAMERA_ROTATE_RATE * get_delta_time ();
	}
	else if (adjust_view_right_key || joystick_pov_right)
	{
		raw->chase_camera_heading -= CHASE_CAMERA_ROTATE_RATE * get_delta_time ();
	}

	raw->chase_camera_heading = wrap_angle (raw->chase_camera_heading);

	//
	// adjust camera pitch
	//

	if (adjust_view_up_key || joystick_pov_up)
	{
		raw->chase_camera_pitch -= CHASE_CAMERA_ROTATE_RATE * get_delta_time ();

		raw->chase_camera_pitch = max (CHASE_CAMERA_ROTATE_DOWN_LIMIT, raw->chase_camera_pitch);
	}
	else if (adjust_view_down_key || joystick_pov_down)
	{
		raw->chase_camera_pitch += CHASE_CAMERA_ROTATE_RATE * get_delta_time ();

		raw->chase_camera_pitch = min (CHASE_CAMERA_ROTATE_UP_LIMIT, raw->chase_camera_pitch);
	}

	if (adjust_view_zoom_in_key)
	{
		raw->chase_camera_zoom -= CHASE_CAMERA_ZOOM_RATE * get_delta_time ();

		raw->chase_camera_zoom = max (CHASE_CAMERA_ZOOM_IN_LIMIT, raw->chase_camera_zoom);
	}
	else if (adjust_view_zoom_out_key)
	{
		raw->chase_camera_zoom += CHASE_CAMERA_ZOOM_RATE * get_delta_time ();

		raw->chase_camera_zoom = min (CHASE_CAMERA_ZOOM_OUT_LIMIT, raw->chase_camera_zoom);
	}

	//
	// get camera attitude
	//

	if (get_local_entity_int_value (en, INT_TYPE_ALIVE) && raw->chase_camera_lock_rotate)
	{
		combined_heading = get_local_entity_float_value (en, FLOAT_TYPE_HEADING);
	}
	else
	{
		combined_heading = 0.0;
	}

	combined_heading += raw->chase_camera_heading;

	get_3d_transformation_matrix (raw->attitude, combined_heading, raw->chase_camera_pitch, 0.0);

	//
	// get camera position
	//

	if (in_flight_zoom_test)
	{
		z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE_TEST);
		z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE_TEST);
	}
	else
	{
		z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE);
		z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE);
	}

	ASSERT (z_min < z_max);

	rel_camera_position.x = 0.0;
	rel_camera_position.y = 0.0;
	rel_camera_position.z = -(((z_max - z_min) * raw->chase_camera_zoom * raw->chase_camera_zoom) + z_min);

	multiply_matrix3x3_vec3d (&rel_camera_position, raw->attitude, &rel_camera_position);

	get_local_entity_target_point (en, &raw->position);

	raw->position.x += rel_camera_position.x;
	raw->position.y += rel_camera_position.y;
	raw->position.z += rel_camera_position.z;

	//
	// 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);
	}

	//
	// motion vector
	//

	get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector);
}
Example #18
0
void draw_debug_guide_entity (entity *en)
{

    waypoint
    *raw;

    entity
    *member,
    *this_waypoint;

    vec3d
    direction,
    guide_pos,
    *member_pos,
    *this_waypoint_position;

    float
    length;

    ASSERT (en);

    raw = (waypoint *) get_local_entity_data (en);

    //
    // get guide position
    //

    get_local_entity_vec3d (en, VEC3D_TYPE_GUIDE_POSITION, &guide_pos);

    //
    // get waypoint position
    //

    this_waypoint_position = NULL;

    this_waypoint = get_local_entity_parent (en, LIST_TYPE_CURRENT_WAYPOINT);

    ASSERT (this_waypoint);

    //
    // draw guide position
    //

    direction.x = 0.0;
    direction.y = 1.0;
    direction.z = 0.0;

    create_vectored_debug_3d_object (&guide_pos, &direction, OBJECT_3D_SPHERICAL_TEST, 0.0, 1.0);

    if (get_local_entity_int_value (this_waypoint, INT_TYPE_POSITION_TYPE) != POSITION_TYPE_VIRTUAL)
    {
        this_waypoint_position = get_local_entity_vec3d_ptr (this_waypoint, VEC3D_TYPE_POSITION);

        length = get_3d_range (&guide_pos, this_waypoint_position);

        if (length > 0.0)
        {
            create_debug_3d_line (&guide_pos, this_waypoint_position, sys_col_yellow, 0.0);
        }
    }

    //
    // draw vector to group position
    //

    member = get_local_entity_first_child (en, LIST_TYPE_FOLLOWER);

    while (member)
    {
        member_pos = get_local_entity_vec3d_ptr (member, VEC3D_TYPE_POSITION);

        length = get_3d_range (&guide_pos, member_pos);

        if (length > 0.0)
        {
            create_debug_3d_line (&guide_pos, member_pos, sys_col_light_red, 0.0);
        }

        member = get_local_entity_child_succ (member, LIST_TYPE_FOLLOWER);
    }
}
Example #19
0
static void get_display_viewpoint (view_modes mode, viewpoint *display_viewpoint)
{
	object_3d_sub_object_index_numbers
		index;

	object_3d_sub_object_search_data
		search;

	viewpoint
		vp;

	ASSERT (display_viewpoint);

	if ((!full_screen_hi_res) && (application_video_colourdepth == 16))
	{
		display_viewpoint->x = 0.0;
		display_viewpoint->y = 0.0;
		display_viewpoint->z = 0.0;

		get_local_entity_attitude_matrix (get_gunship_entity (), display_viewpoint->attitude);

		return;
	}

	if (mode == VIEW_MODE_COCKPIT_PANEL_SPECIAL_APACHE_LHS_MFD)
	{
		index = OBJECT_3D_SUB_OBJECT_APACHE_COCKPIT_LHS_MFD_CAMERA;
	}
	else if (mode == VIEW_MODE_COCKPIT_PANEL_SPECIAL_APACHE_RHS_MFD)
	{
		index = OBJECT_3D_SUB_OBJECT_APACHE_COCKPIT_RHS_MFD_CAMERA;
	}
	else
	{
		debug_fatal ("Invalid view mode = %d", mode);
	}

	virtual_cockpit_inst3d = virtual_cockpit_level1_inst3d;

	search.search_depth = 0;
	search.search_object = virtual_cockpit_inst3d;
	search.sub_object_index = index;

	if (find_object_3d_sub_object (&search) != SUB_OBJECT_SEARCH_RESULT_OBJECT_FOUND)
	{
		debug_fatal ("Failed to locate display viewpoint in virtual cockpit");
	}

	virtual_cockpit_inst3d->vp.x = 0.0;
	virtual_cockpit_inst3d->vp.y = 0.0;
	virtual_cockpit_inst3d->vp.z = 0.0;

	get_local_entity_attitude_matrix (get_gunship_entity (), virtual_cockpit_inst3d->vp.attitude);

	get_3d_sub_object_world_viewpoint (search.result_sub_object, &vp);

	get_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &main_vp.position);

	main_vp.x += vp.x;
	main_vp.y += vp.y;
	main_vp.z += vp.z;

	memcpy (main_vp.attitude, vp.attitude, sizeof (matrix3x3));

	vp.x = -vp.x;
	vp.y = -vp.y;
	vp.z = -vp.z;

	multiply_transpose_matrix3x3_vec3d (&virtual_cockpit_inst3d->vp.position, vp.attitude, &vp.position);

	memcpy (display_viewpoint, &virtual_cockpit_inst3d->vp, sizeof (viewpoint));
}
Example #20
0
static void kill_local (entity *en)
{
	object
		*raw;

	vec3d
		pos;

	////////////////////////////////////////
	//
	// PRE-AMBLE
	//
	////////////////////////////////////////

	#if DEBUG_MODULE

	debug_log_entity_args (ENTITY_DEBUG_LOCAL, ENTITY_DEBUG_KILL, en);

	#endif

	raw = (object *) get_local_entity_data (en);

	set_local_entity_int_value (en, INT_TYPE_ALIVE, FALSE);

	////////////////////////////////////////
	//
	// UNLINK FROM SYSTEM
	//
	////////////////////////////////////////

	//
	// fixed
	//

	unlink_local_entity_children (en, LIST_TYPE_TASK_DEPENDENT);

	unlink_local_entity_children (en, LIST_TYPE_TARGET);

	// gunship_target_link

	// sector_link

	//
	// object
	//

	////////////////////////////////////////
	//
	// SPECIAL EFFECTS
	//
	////////////////////////////////////////

	if (get_comms_model () == COMMS_MODEL_SERVER)
	{
		create_client_server_object_killed_explosion_effect (en);

		get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &pos);

		pos.y = get_3d_terrain_elevation (pos.x, pos.z);

		create_client_server_crater (CRATER_TYPE_LARGE_EXPLOSION, &pos);
	}

	//
	// must be done AFTER object explosion
	//

	raw->fix.object_3d_shape = get_3d_object_destroyed_object_index (raw->fix.object_3d_shape);
}
Example #21
0
static entity *create_local (entity_types type, int index, char *pargs)
{

	entity
		*en;

	waypoint
		*raw;

	vec3d
		v;

	////////////////////////////////////////
  	//
  	// 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 (waypoint));

		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 (waypoint));

		raw->position.x = MID_MAP_X;
		raw->position.z = MID_MAP_Z;
		raw->position.y = MID_MAP_Y;

		raw->sub_type = ENTITY_SUB_TYPE_WAYPOINT_NAVIGATION;

		raw->waypoint_formation = FORMATION_ROW_LEFT;

		raw->position_type = POSITION_TYPE_ABSOLUTE;

		raw->heading = 0.0;

		////////////////////////////////////////
		//
		// OVERWRITE DEFAULT VALUES WITH GIVEN ATTRIBUTES
		//
		////////////////////////////////////////

		set_local_entity_attributes (en, pargs);

		////////////////////////////////////////
		//
		// CHECK MANDATORY ATTRIBUTES HAVE BEEN GIVEN
		//
		////////////////////////////////////////

		ASSERT (raw->waypoint_link.parent);

		get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &v);

		ASSERT (point_inside_map_volume (&v));

		////////////////////////////////////////
		//
		// RESOLVE DEFAULT VALUES
		//
		////////////////////////////////////////

		////////////////////////////////////////
		//
		// LINK INTO SYSTEM
		//
		////////////////////////////////////////

		if (raw->task_dependent_link.parent)
		{

			insert_local_entity_into_parents_child_list (en, LIST_TYPE_TASK_DEPENDENT, raw->task_dependent_link.parent, NULL);
		}

		insert_local_entity_into_parents_child_list (en, LIST_TYPE_WAYPOINT, raw->waypoint_link.parent, raw->waypoint_link.child_pred);

		#if DEBUG_MODULE

		insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, get_local_sector_entity (&raw->position), NULL);

		#endif
	}

	return (en);
}
Example #22
0
void vector_dynamics_velocity (event *ev)
{

	if (ev->modifier == MODIFIER_RIGHT_SHIFT)
	{

		switch (ev->key)
		{

			case DIK_Q:
			{

				current_flight_dynamics->velocity_z.value = 1000;

				break;
			}

			case DIK_A:
			{

				current_flight_dynamics->velocity_z.value = 0.0;

				break;
			}
		}
	}
	else if (ev->modifier == MODIFIER_RIGHT_ALT)
	{

		switch (ev->key)
		{

			case DIK_Q:
			{

				vec3d
					pos;

				get_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &pos);

				pos.y += 10;

				set_client_server_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &pos);

				break;
			}

			case DIK_A:
			{

				vec3d
					pos;

				get_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &pos);

				pos.y -= 10;

				set_client_server_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &pos);

				break;
			}
		}
	}
	else 
	{

		switch (ev->key)
		{

			case DIK_Q:
			{

				current_flight_dynamics->velocity_z.value += 20;

				break;
			}

			case DIK_A:
			{

				current_flight_dynamics->velocity_z.value -= 20;

				break;
			}
		}
	}

	current_flight_dynamics->velocity_z.value = bound (current_flight_dynamics->velocity_z.value, -1000, 1000);
}
Example #23
0
aircraft_fire_result aircraft_fire_weapon (entity *en, unsigned int check_flags)
{
	entity
		*target;

	aircraft
		*raw;

	vec3d
		*target_pos,
		en_pos;

	int loal_mode = FALSE;

	ASSERT (en);

	raw = (aircraft *) get_local_entity_data (en);

	//
	// Fire suppressed
	//

	if (check_flags & AIRCRAFT_FIRE_SUPPRESSED)
	{
		if (get_local_entity_int_value (get_session_entity (), INT_TYPE_SUPPRESS_AI_FIRE))
		{
			return AIRCRAFT_FIRE_SUPPRESSED;
		}
	}

	//
	// check weapon
	//

	if (check_flags & AIRCRAFT_FIRE_NO_WEAPON)
	{
		if (get_local_entity_int_value (en, INT_TYPE_SELECTED_WEAPON) == ENTITY_SUB_TYPE_WEAPON_NO_WEAPON)
		{
			debug_log ("AC_WPN: Fire Weapon Error - NO WEAPON");

			return AIRCRAFT_FIRE_NO_WEAPON;
		}
	}

	//
	// weapon system_ready
	//

	if (check_flags & AIRCRAFT_FIRE_WEAPON_SYSTEM_NOT_READY)
	{
		if (!get_local_entity_int_value (en, INT_TYPE_SELECTED_WEAPON_SYSTEM_READY))
		{
			debug_log ("AC_WPN: Fire Weapon Error - WEAPON SYSTEM NOT READY");

			return AIRCRAFT_FIRE_WEAPON_SYSTEM_NOT_READY;
		}
	}

//	debug_log("%s: %d", get_sub_type_name(en), get_local_entity_int_value (en, INT_TYPE_SELECTED_WEAPON));

	//
	// find target
	//

	if (check_flags & AIRCRAFT_FIRE_NO_TARGET)
	{
		target = get_local_entity_parent (en, LIST_TYPE_TARGET);

		if (!target)
		{
			debug_log ("AC_WPN: Fire Weapon Error - NO TARGET");

			return AIRCRAFT_FIRE_NO_TARGET;
		}
	}

	//
	// line of sight checks
	//

	if (check_flags & AIRCRAFT_FIRE_NO_LOS)
	{
		int
			criteria;

		if (get_local_entity_int_value (target, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI)
		{
			criteria = MOBILE_LOS_CHECK_ALL;
		}
		else
		{
			criteria = MOBILE_LOS_CHECK_COURSE_TERRAIN;
		}

		get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &en_pos);

		target_pos = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION);

		en_pos.y -= (get_local_entity_float_value (en, FLOAT_TYPE_CENTRE_OF_GRAVITY_TO_GROUND_DISTANCE) + 2.0);

		if (!check_position_line_of_sight (en, target, &en_pos, target_pos, (mobile_los_check_criteria) criteria))
		{
			if (get_local_entity_int_value (en, INT_TYPE_SELECTED_WEAPON) == ENTITY_SUB_TYPE_WEAPON_AGM114L_LONGBOW_HELLFIRE
				&& get_2d_range(&en_pos, target_pos) > weapon_database[ENTITY_SUB_TYPE_WEAPON_AGM114L_LONGBOW_HELLFIRE].min_range_loal)
			{
				debug_log("AC_WPN: Switching to LOAL mode to fire at target without LOS ((Aircraft %s (%d), Target %s (%d))",
									get_local_entity_string (en, STRING_TYPE_FULL_NAME), get_local_entity_index (en),
									get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target));

				loal_mode = TRUE;
			}
			else
			{
				debug_log ("AC_WPN: Fire Weapon Error - NO LOS (Aircraft %s (%d), Target %s (%d))",
									get_local_entity_string (en, STRING_TYPE_FULL_NAME), get_local_entity_index (en),
									get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target));

				return AIRCRAFT_FIRE_NO_LOS;
			}
		}
	}

	//
	// Play Speech
	//

	play_aircraft_weapon_launched_speech (en, raw->selected_weapon);

	//
	// Fire weapon
	//

	set_local_entity_int_value(en, INT_TYPE_LOCK_ON_AFTER_LAUNCH, loal_mode);

	launch_client_server_weapon (en, raw->selected_weapon);

	return AIRCRAFT_FIRE_OK;
}
Example #24
0
void reset_static_camera (camera *raw)
{
	entity
		*en;

	vec3d
		pos,
		v;

	matrix3x3
		m;

	float
		heading,
		z_min,
		z_max,
		radius,
		length;

	int
		fast_airborne;

	ASSERT (raw);

	ASSERT (raw->external_view_entity);

	en = raw->external_view_entity;

	z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE);
	z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE);

	ASSERT (z_min < z_max);

	radius = -(((z_max - z_min) * CHASE_CAMERA_RESET_ZOOM * CHASE_CAMERA_RESET_ZOOM) + z_min);

	fast_airborne = FALSE;

	if (get_local_entity_int_value (en, INT_TYPE_AIRBORNE_AIRCRAFT))
	{
		if (get_local_entity_vec3d_magnitude (en, VEC3D_TYPE_MOTION_VECTOR) >= knots_to_metres_per_second (10.0))
		{
			fast_airborne = TRUE;
		}
	}

	if (fast_airborne)
	{
		get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &v);

		normalise_3d_vector (&v);

		v.x *= radius;
		v.y *= radius;
		v.z *= radius;
	}
	else
	{
		heading = get_local_entity_float_value (en, FLOAT_TYPE_HEADING);

		get_3d_transformation_matrix (m, heading, CHASE_CAMERA_RESET_PITCH, 0.0);

		v.x = 0.0;
		v.y = 0.0;
		v.z = radius;

		multiply_matrix3x3_vec3d (&v, m, &v);
	}

	get_local_entity_target_point (en, &pos);

	raw->position.x = pos.x + v.x;
	raw->position.y = pos.y + v.y;
	raw->position.z = pos.z + v.z;

	//
	// 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);
	}

	//
	// attitude
	//

	v.x = pos.x - raw->position.x;
	v.y = pos.y - raw->position.y;
	v.z = pos.z - raw->position.z;

	length = (v.x * v.x) + (v.y * v.y) + (v.z * v.z);

	if (length > 1.0)
	{
		length = sqrt (length);

		normalise_3d_vector_given_magnitude (&v, length);

		get_matrix3x3_from_unit_vec3d (raw->attitude, &v);
	}
	else
	{
		get_identity_matrix3x3 (raw->attitude);
	}

	//
	// motion vector
	//

	raw->motion_vector.x = 0.0;
	raw->motion_vector.y = 0.0;
	raw->motion_vector.z = 0.0;
}
Example #25
0
void get_hokum_display_viewpoint (view_modes mode)
{
	object_3d_sub_object_index_numbers
		index;

	object_3d_sub_object_search_data
		search;

	vec3d
		position;

	ASSERT (get_gunship_entity ());

	ASSERT (virtual_cockpit_inst3d);

	switch (mode)
	{
		////////////////////////////////////////
		case VIEW_MODE_VIRTUAL_COCKPIT_PILOT_LHS_DISPLAY:
		////////////////////////////////////////
		{
			index = OBJECT_3D_SUB_OBJECT_COCKPIT_VIEW_MFD_LHS_2;

			break;
		}
		////////////////////////////////////////
		case VIEW_MODE_VIRTUAL_COCKPIT_PILOT_RHS_DISPLAY:
		////////////////////////////////////////
		{
			index = OBJECT_3D_SUB_OBJECT_COCKPIT_VIEW_MFD_LHS_1;

			break;
		}
		////////////////////////////////////////
		case VIEW_MODE_VIRTUAL_COCKPIT_CO_PILOT_LHS_DISPLAY:
		////////////////////////////////////////
		{
			index = OBJECT_3D_SUB_OBJECT_COCKPIT_VIEW_MFD_RHS_1;

			break;
		}
		////////////////////////////////////////
		case VIEW_MODE_VIRTUAL_COCKPIT_CO_PILOT_RHS_DISPLAY:
		////////////////////////////////////////
		{
			index = OBJECT_3D_SUB_OBJECT_COCKPIT_VIEW_MFD_RHS_2;

			break;
		}
		////////////////////////////////////////
		default:
		////////////////////////////////////////
		{
			debug_fatal ("Invalid view mode = %d", mode);

			break;
		}
	}

	virtual_cockpit_inst3d->vp.x = 0.0;
	virtual_cockpit_inst3d->vp.y = 0.0;
	virtual_cockpit_inst3d->vp.z = 0.0;

	get_local_entity_attitude_matrix (get_gunship_entity (), virtual_cockpit_inst3d->vp.attitude);

	search.search_depth = 0;
	search.search_object = virtual_cockpit_inst3d;
	search.sub_object_index = index;

	if (find_object_3d_sub_object (&search) == SUB_OBJECT_SEARCH_RESULT_OBJECT_FOUND)
	{
		get_3d_sub_object_world_viewpoint (search.result_sub_object, &main_vp);
	}
	else
	{
		debug_fatal ("Failed to locate display viewpoint in virtual cockpit");
	}

	position.x = -main_vp.x;
	position.y = -main_vp.y;
	position.z = -main_vp.z;

	multiply_transpose_matrix3x3_vec3d (&virtual_cockpit_inst3d->vp.position, main_vp.attitude, &position);

	get_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &position);

	main_vp.x += position.x;
	main_vp.y += position.y;
	main_vp.z += position.z;
}
Example #26
0
static void kill_local (entity *en)
{
	site
		*raw;

	vec3d
		pos;

	entity
		*task,
		*destroy_task;

	////////////////////////////////////////
	//
	// PRE-AMBLE
	//
	////////////////////////////////////////

	#if DEBUG_MODULE

	debug_log_entity_args (ENTITY_DEBUG_LOCAL, ENTITY_DEBUG_KILL, en);

	#endif

	raw = get_local_entity_data (en);

	////////////////////////////////////////
	//
	// UNLINK FROM SYSTEM
	//
	////////////////////////////////////////

	if (get_comms_model () == COMMS_MODEL_SERVER)
	{
		task = get_local_entity_first_child (en, LIST_TYPE_TASK_DEPENDENT);

		while (task)
		{

			destroy_task = task;

			task = get_local_entity_child_succ (task, LIST_TYPE_TASK_DEPENDENT);

			if (destroy_task->type == ENTITY_TYPE_TASK)
			{

				#if DEBUG_MODULE

				debug_log ("ST_DSTRY: killing site, 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);
			}
		}
	}

	//
	// fixed
	//

	unlink_local_entity_children (en, LIST_TYPE_TASK_DEPENDENT);

	unlink_local_entity_children (en, LIST_TYPE_TARGET);

	// gunship_target_link

	// sector_link

	//
	// site
	//

	////////////////////////////////////////
	//
 	// KILL
	//
	////////////////////////////////////////

	// must be done BEFORE alive flag set
	subtract_local_entity_importance_from_keysite (en);

	set_local_entity_int_value (en, INT_TYPE_ALIVE, FALSE);

	////////////////////////////////////////
	//
	// SPECIAL EFFECTS
	//
	////////////////////////////////////////

	if (get_comms_model () == COMMS_MODEL_SERVER)
	{
		create_client_server_object_killed_explosion_effect (en);

		get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &pos);

		pos.y = get_3d_terrain_elevation (pos.x, pos.z);

		create_client_server_crater (CRATER_TYPE_LARGE_EXPLOSION, &pos);
	}

	//
	// must be done AFTER object explosion
	//

	raw->fix.object_3d_shape = get_3d_object_destroyed_object_index (raw->fix.object_3d_shape);
}
Example #27
0
void update_cinematic_camera_continued (camera *raw)
{
	entity
		*en;

	object_3d_instance
		*inst3d;

	viewpoint
		vp;

	float
		normalised_timer;

	//
	// pre-amble
	//

	ASSERT (raw);

	ASSERT (raw->external_view_entity);

	en = raw->external_view_entity;

	//
	// get camera position and attitude
	//

	switch (raw->cinematic_camera_index)
	{
		////////////////////////////////////////
		case OBJECT_3D_INVALID_CAMERA_INDEX:
		////////////////////////////////////////
		{
			float
				combined_heading,
				z_min,
				z_max;

			vec3d
				rel_camera_position;

			combined_heading = get_local_entity_float_value (en, FLOAT_TYPE_HEADING);

			combined_heading += raw->cinematic_camera_heading;

			get_3d_transformation_matrix (raw->attitude, combined_heading, raw->cinematic_camera_pitch, 0.0);

			z_min = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MIN_DISTANCE);
			z_max = get_local_entity_float_value (en, FLOAT_TYPE_CHASE_VIEW_MAX_DISTANCE);

			ASSERT (z_min < z_max);

			rel_camera_position.x = 0.0;
			rel_camera_position.y = 0.0;
			rel_camera_position.z = -(((z_max - z_min) * 0.1) + z_min);

			multiply_matrix3x3_vec3d (&rel_camera_position, raw->attitude, &rel_camera_position);

			get_local_entity_target_point (en, &raw->position);

			raw->position.x += rel_camera_position.x;
			raw->position.y += rel_camera_position.y;
			raw->position.z += rel_camera_position.z;

			break;
		}
		////////////////////////////////////////
		case OBJECT_3D_CAMERA_SCENIC_MOVING:
		////////////////////////////////////////
		{
			normalised_timer = raw->cinematic_camera_timer / raw->cinematic_camera_lifetime;

			inst3d = get_local_entity_ptr_value (en, PTR_TYPE_INSTANCE_3D_OBJECT);

			get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &inst3d->vp.position);

			get_local_entity_attitude_matrix (en, inst3d->vp.attitude);

			get_object_3d_camera_position (inst3d, raw->cinematic_camera_index, raw->cinematic_camera_depth, normalised_timer, &vp);

			raw->position = vp.position;

			memcpy (raw->attitude, vp.attitude, sizeof (matrix3x3));

			break;
		}
		////////////////////////////////////////
		case OBJECT_3D_CAMERA_SCENIC_STATIC:
		////////////////////////////////////////
		{
			normalised_timer = 0.0;

			inst3d = get_local_entity_ptr_value (en, PTR_TYPE_INSTANCE_3D_OBJECT);

			get_local_entity_vec3d (en, VEC3D_TYPE_POSITION, &inst3d->vp.position);

			get_local_entity_attitude_matrix (en, inst3d->vp.attitude);

			get_object_3d_camera_position (inst3d, raw->cinematic_camera_index, raw->cinematic_camera_depth, normalised_timer, &vp);

			raw->position = vp.position;

			memcpy (raw->attitude, vp.attitude, sizeof (matrix3x3));

			break;
		}
	}

	//
	// 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) + 0.5);
	}

	//
	// motion vector
	//

	get_local_entity_vec3d (en, VEC3D_TYPE_MOTION_VECTOR, &raw->motion_vector);
}
Example #28
0
void get_hokum_crew_viewpoint (void)
{
	object_3d_sub_object_search_data
		search_head,
		search_viewpoint;

	viewpoint
		vp;

	float
		head_pitch_datum;

	//
	// select head
	//

	if (get_local_entity_int_value (get_pilot_entity (), INT_TYPE_CREW_ROLE) == CREW_ROLE_PILOT)
	{
		search_head.sub_object_index = OBJECT_3D_SUB_OBJECT_PILOT_HEAD;

		search_viewpoint.sub_object_index = OBJECT_3D_SUB_OBJECT_PILOT_VIEWPOINT;

		head_pitch_datum = pilot_head_pitch_datum;
	}
	else
	{
		search_head.sub_object_index = OBJECT_3D_SUB_OBJECT_WSO_HEAD;

		search_viewpoint.sub_object_index = OBJECT_3D_SUB_OBJECT_WSO_VIEWPOINT;

		head_pitch_datum = co_pilot_head_pitch_datum;
	}

	//
	// rotate head
	//

	search_head.search_depth = 0;
	search_head.search_object = virtual_cockpit_inst3d;

	if (find_object_3d_sub_object (&search_head) == SUB_OBJECT_SEARCH_RESULT_OBJECT_FOUND)
	{
		search_head.result_sub_object->relative_heading = -pilot_head_heading;
		search_head.result_sub_object->relative_pitch = head_pitch_datum - pilot_head_pitch;
		search_head.result_sub_object->relative_roll = 0.0;
	}
	else
	{
		debug_fatal ("Failed to locate crew's head in virtual cockpit");
	}

	//
	// get viewpoint (avoid jitter)
	//

	search_viewpoint.search_object = virtual_cockpit_inst3d;
	search_viewpoint.search_depth = 0;

	if (find_object_3d_sub_object (&search_viewpoint) == SUB_OBJECT_SEARCH_RESULT_OBJECT_FOUND)
	{
		virtual_cockpit_inst3d->vp.x = 0.0;
		virtual_cockpit_inst3d->vp.y = 0.0;
		virtual_cockpit_inst3d->vp.z = 0.0;

		get_local_entity_attitude_matrix (get_gunship_entity (), virtual_cockpit_inst3d->vp.attitude);

		get_3d_sub_object_world_viewpoint (search_viewpoint.result_sub_object, &vp);

		get_local_entity_vec3d (get_gunship_entity (), VEC3D_TYPE_POSITION, &pilot_head_vp.position);

		pilot_head_vp.x += vp.x;
		pilot_head_vp.y += vp.y;
		pilot_head_vp.z += vp.z;

		memcpy (pilot_head_vp.attitude, vp.attitude, sizeof (matrix3x3));

		vp.x = -vp.x;
		vp.y = -vp.y;
		vp.z = -vp.z;

		multiply_transpose_matrix3x3_vec3d (&virtual_cockpit_inst3d->vp.position, pilot_head_vp.attitude, &vp.position);
	}
	else
	{
		debug_fatal ("Failed to locate crew's viewpoint in virtual cockpit");
	}
}
Example #29
0
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);
}