Esempio n. 1
0
int create_downwash_effect_component(downwash_component *this_downwash_component, downwash_types downwash_type, vec3d *position, int *entity_index_list, float main_rotor_radius, float main_rotor_rpm, float min_altitude)
{
	int
		loop,
		count,
		terrain_type,
		trail_type;

	short int
		quadrant_x,
		quadrant_z;
	
	unsigned char
		alpha_percentage;

	float
		lifetime,
		lifetime_min,
		lifetime_max,
		scale_min,
		scale_max,
		scale,
		angle,
		radius,
		relative_radius,
		height,
		altitude,
		half_altitude,
		main_rotor_radius_minus_altitude;

	vec3d
		pos,
		offset,
		iv;

	terrain_3d_point_data
		terrain_info;

	entity
		*new_entity;

	memset (&terrain_info, 0, sizeof (terrain_3d_point_data));

	count = this_downwash_component->trail_count;

	if ( count < 1 )
	{
		return 0;
	}

	// Xhit: This is the altitude of the helicopter relative to the ground level. (030328)
	altitude = position->y - min_altitude;
	half_altitude = (altitude / 2.0);

	main_rotor_radius_minus_altitude = main_rotor_radius - altitude;

	scale_min = this_downwash_component->scale_min;
	scale_max = this_downwash_component->scale_max;

	lifetime_min = this_downwash_component->lifetime_min;
	lifetime_max = this_downwash_component->lifetime_max;

	// Xhit: initialising quadrant variables (030328)
	quadrant_x = 1;
	quadrant_z = 1;

	//
	// create smoke trails
	//

	for ( loop = 0 ; loop < count ; loop ++ )
	{
		lifetime = lifetime_min + fabs( ( lifetime_max - lifetime_min ) * sfrand1() );

		angle = frand1() * PI_OVER_TWO;

		relative_radius = main_rotor_radius * frand1();

		scale = relative_radius + scale_min;
		if(scale > scale_max)
				scale = scale_max;

		switch(downwash_type)
		{
			case DOWNWASH_TYPE_LAND:
			case DOWNWASH_TYPE_LAND_DUAL_ROTORS:
			{
				//Xhit: If altitude bigger than main rotor radius then the smoke should be centered beneath the helicopter. (030328)
				if(altitude >= main_rotor_radius)
				{
					radius = relative_radius;
					height = (half_altitude * (radius / main_rotor_radius) + half_altitude) * frand1();
			
				}else
				{
					radius = relative_radius + main_rotor_radius_minus_altitude;
					height = (half_altitude * ((radius - main_rotor_radius_minus_altitude) / main_rotor_radius) + half_altitude + scale ) * frand1();
				}
				break;
			}
			case DOWNWASH_TYPE_WATER:
			case DOWNWASH_TYPE_WATER_DUAL_ROTORS:
			{
				if(altitude >= main_rotor_radius)
				{
					radius = relative_radius;
			
				}else
				{
					radius = relative_radius + main_rotor_radius_minus_altitude;
				}

				// Xhit: Changed to 2 instead of main_rotor_radius so smoke is created just over water level (030515)
				height =  2 * frand1();
				break;
			}
			default:
			{
				debug_fatal("DOWNWASH : trying to create an unrecogniseable downwash effect");
				break;
			}
		}


		//Xhit: If main rotor(s) only (not displaced main rotors) then. (030328)
		if((this_downwash_component->create_in_all_quadrants) && (loop < 4))
		{
			//Xhit:	This cryptical thing is to determine in which quadrant this sprite is going to be created. (030328)
			//		 ^z
			//		 |
			//		1|0  x
			//		-+--->
			//		3|2
			//
			//		loop = 0 -> x=	1,	z=	1; loop = 1 -> x=	-1, z=	 1;
			//		loop = 2 -> x=   1,	z= -1; loop = 3 -> x=	-1, z=	-1;
			quadrant_x = 1 | -(loop & 1);
			quadrant_z = 1 | -(loop & 2);
						
			offset.x = quadrant_x * radius * ( cos ( angle ) );
			offset.y = height;
			offset.z = quadrant_z * radius * ( sin ( angle ) );

		}else
		//Xhit:	If scattered downwash effect and if the heli got more than one main rotor (on different axis) then 
		//			add two more trails at the sides of the heli. (030328)
		if((this_downwash_component->create_in_all_quadrants) && (loop >= 4) && (count == 6))
		{
			//Xhit: loop = 4 -> x=	1; loop = 5 -> x=	-1; (030328)
			quadrant_x = 1 | -(loop & 1);

			relative_radius = main_rotor_radius * frand1();

			offset.x = quadrant_x * radius;
			offset.y = height;
			offset.z = frand1() * (main_rotor_radius / 2);
		}else
		{
			debug_fatal("DOWNWASH : trying to create an unrecogniseable downwash effect");
		}

		pos.x = position->x + offset.x ;
		pos.z = position->z + offset.z;

		//Xhit: This is necessary if it's going to work on tilting terrain. (030328)
		get_3d_terrain_point_data (pos.x, pos.z, &terrain_info);
		pos.y = get_3d_terrain_point_data_elevation (&terrain_info);

		pos.y = pos.y + offset.y;

		bound_position_to_map_volume( &pos );

		//Xhit: Decide which trail type is going to be used, this makes mapping to type of downwash effect fast. (030328)
		terrain_type = get_3d_terrain_point_data_type(&terrain_info);
		trail_type = get_terrain_surface_type(terrain_type) + SMOKE_LIST_TYPE_DOWNWASH_START;

		#if DEBUG_MODULE
		
		debug_log("DOWNWASH.C: terrain_type: %d, trail_type: %d", terrain_type, trail_type);

		#endif		

		iv.x = pos.x - position->x;
		iv.y = relative_radius;
		iv.z = pos.z - position->z;

		//Xhit:	If heli on ground then let the dust-smoke fade in according to increasing main_rotor_rpm
		//		otherwise set it according to the altitude of the heli (higher = less dust smoke) (030328)
		if(altitude < 1.0)
		{
			alpha_percentage = (unsigned char)(main_rotor_rpm);
		}else
		{
			//Xhit: "+ 1.0" is to guarantee that alpha_percentage > 0. (030328)
			alpha_percentage = (unsigned char)((1.0 - (altitude / (DOWNWASH_EFFECT_MAX_ALTITUDE + 1.0))) * 100);
		}

		new_entity = create_local_entity
		(
			ENTITY_TYPE_SMOKE_LIST,
			entity_index_list[ loop ],
			ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, ENTITY_SUB_TYPE_EFFECT_SMOKE_LIST_DOWNWASH),
			ENTITY_ATTR_INT_VALUE (INT_TYPE_SMOKE_TYPE, trail_type),
			ENTITY_ATTR_INT_VALUE (INT_TYPE_COLOUR_ALPHA, alpha_percentage),
			ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_GENERATOR_LIFETIME, this_downwash_component->generator_lifetime),
			ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_FREQUENCY, this_downwash_component->frequency),
			ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_SMOKE_LIFETIME, lifetime),
			ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_SCALE, scale),
			ENTITY_ATTR_VEC3D (VEC3D_TYPE_INITIAL_VELOCITY, iv.x, iv.y, iv.z),
			ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, pos.x, pos.y, pos.z),
			ENTITY_ATTR_END
		);

		entity_index_list[ loop ] = get_local_entity_index( new_entity );
	}

	return count;
}
Esempio n. 2
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);
}