Beispiel #1
0
entity *create_new_pilot_entity (const char *name, entity_sides side, int rank, entity_sub_types sub_type, int unique_id, int difficulty)
{
	entity
		*en,
		*force;

	ASSERT (get_comms_model () == COMMS_MODEL_SERVER);
	
	ASSERT (name);

	force = get_local_force_entity (side);

	ASSERT (force);

	en = create_client_server_entity
				(
					ENTITY_TYPE_PILOT,
					ENTITY_INDEX_DONT_CARE,
					ENTITY_ATTR_PARENT (LIST_TYPE_PILOT, force),
					ENTITY_ATTR_STRING (STRING_TYPE_PILOTS_NAME, name),
					ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, sub_type),
					ENTITY_ATTR_INT_VALUE (INT_TYPE_UNIQUE_ID, unique_id),
					ENTITY_ATTR_INT_VALUE (INT_TYPE_SIDE, side),
					ENTITY_ATTR_INT_VALUE (INT_TYPE_PILOT_RANK, rank),
					ENTITY_ATTR_INT_VALUE (INT_TYPE_DIFFICULTY_LEVEL, difficulty),
					ENTITY_ATTR_END
				);

	send_pilot_joined_message (en);

	return en;
}
Beispiel #2
0
entity *create_local_entity_routed_vehicle (int index, entity_sub_types sub_type, entity *group, vec3d *position)
{
	entity
		*new_entity;

	ASSERT (get_comms_model() == COMMS_MODEL_SERVER);

	//
	// create routed entity
	//

	new_entity = create_local_entity
	(
		ENTITY_TYPE_ROUTED_VEHICLE,
		index,
		ENTITY_ATTR_PARENT (LIST_TYPE_MEMBER, group),
		ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, sub_type),
		ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, position->x, position->y, position->z),
		ENTITY_ATTR_END
	);

	//
	// create and attach special effects
	//

	//
	//
	//

	return new_entity;
}
Beispiel #3
0
entity *create_new_division (entity_sub_types type, entity_sides side, entity *parent, entity *hq, int local_only)
{
	entity
		*new_entity;

	int
		id;

	ASSERT (get_comms_model () == COMMS_MODEL_SERVER);

	ASSERT (parent);

	id = get_next_free_division_id (side, type);

	if (local_only)
	{
		new_entity = create_local_entity
		(
			ENTITY_TYPE_DIVISION,
			ENTITY_INDEX_DONT_CARE,
			ENTITY_ATTR_PARENT (LIST_TYPE_DIVISION, parent),
			ENTITY_ATTR_PARENT (LIST_TYPE_DIVISION_HEADQUARTERS, hq),
			ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, type),
			ENTITY_ATTR_INT_VALUE (INT_TYPE_DIVISION_ID, id),
			ENTITY_ATTR_END
		);
	}
	else
	{
		new_entity = create_client_server_entity
		(
			ENTITY_TYPE_DIVISION,
			ENTITY_INDEX_DONT_CARE,
			ENTITY_ATTR_PARENT (LIST_TYPE_DIVISION, parent),
			ENTITY_ATTR_PARENT (LIST_TYPE_DIVISION_HEADQUARTERS, hq),
			ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, type),
			ENTITY_ATTR_INT_VALUE (INT_TYPE_DIVISION_ID, id),
			ENTITY_ATTR_END
		);
	}

	return new_entity;
}
Beispiel #4
0
entity *create_client_server_entity_routed_vehicle (int index, entity_sub_types sub_type, entity *group, vec3d *position)
{
	entity
		*new_entity;

	sound_sample_indices
		sample_index;

	ASSERT (get_comms_model() == COMMS_MODEL_SERVER);

	//
	// create routed entity
	//

	new_entity = create_client_server_entity
	(
		ENTITY_TYPE_ROUTED_VEHICLE,
		index,
		ENTITY_ATTR_PARENT (LIST_TYPE_MEMBER, group),
		ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, sub_type),
		ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, position->x, position->y, position->z),
		ENTITY_ATTR_END
	);

	//
	// create and attach special effects
	//

	{
		//
		// dust trails
		//

		attach_routed_vehicle_meta_smoke_lists (new_entity);

		//
		// headlights
		//

		set_vehicle_headlight_state (new_entity, OFF);

		//
		// sound effects
		//

		sample_index = vehicle_database [sub_type].idle_sound_effect;

		if (sample_index != SOUND_SAMPLE_INDEX_NONE)
		{
			create_client_server_sound_effect_entity
			(
				new_entity,
				ENTITY_SIDE_NEUTRAL,
				ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING1,
				SOUND_CHANNEL_SOUND_EFFECT,
				SOUND_LOCALITY_ALL,
				NULL,												// position
				1.0,												// amplification
				TRUE,												// valid sound effect
				TRUE,												// looping
				1,													// sample count
				&sample_index									// sample index list
			);
		}

		sample_index = vehicle_database [sub_type].moving_sound_effect;

		if (sample_index != SOUND_SAMPLE_INDEX_NONE)
		{
			create_client_server_sound_effect_entity
			(
				new_entity,
				ENTITY_SIDE_NEUTRAL,
				ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING2,
				SOUND_CHANNEL_SOUND_EFFECT,
				SOUND_LOCALITY_ALL,
				NULL,												// position
				1.0,												// amplification
				FALSE,											// valid sound effect
				TRUE,												// looping
				1,													// sample count
				&sample_index									// sample index list
			);
		}
	}

	//
	//
	//

	return new_entity;
}
Beispiel #5
0
static entity *create_local (entity_types type, int index, char *pargs)
{

	char
		 name [STRING_TYPE_KEYSITE_NAME_MAX_LENGTH];

	entity
		*group,
		*force,
		*sector,
		*en;

	keysite
		*raw;

	////////////////////////////////////////
  	//
  	// VALIDATE
  	//
	////////////////////////////////////////

	validate_local_create_entity_index (index);

	#if DEBUG_MODULE

	debug_log_entity_args (ENTITY_DEBUG_LOCAL, ENTITY_DEBUG_CREATE, NULL, type, index);

	#endif

	en = get_free_entity (index);

	if (en)
	{
		////////////////////////////////////////
   	//
   	// MALLOC ENTITY DATA
   	//
		////////////////////////////////////////

		set_local_entity_type (en, type);

		raw = malloc_fast_mem (sizeof (keysite));

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

		sprintf (name, "KEYSITE %d", (int) en % 100);

		strncpy (raw->keysite_name, name, STRING_TYPE_KEYSITE_NAME_MAX_LENGTH);

		//
		// fixed
		//

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

		raw->alive = TRUE;

		raw->keysite_usable_state = KEYSITE_STATE_USABLE;

		raw->in_use = FALSE;
		raw->object_index = OBJECT_3D_INVALID_OBJECT_INDEX;

		raw->side = ENTITY_SIDE_NEUTRAL;

		raw->supplies.ammo_supply_level = 0.0;

		raw->supplies.fuel_supply_level = 0.0;

		raw->assign_timer = frand1 () * KEYSITE_TASK_ASSIGN_TIMER;		// SERVER ONLY - OK TO USE RANDOM

		raw->sleep = frand1 () * KEYSITE_UPDATE_SLEEP_TIMER;				// SERVER ONLY - OK TO USE RANDOM

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

		set_local_entity_attributes (en, pargs);

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

		ASSERT (raw->side != ENTITY_SIDE_NEUTRAL);

		ASSERT (entity_sub_type_keysite_valid (raw->sub_type));

		ASSERT (keysite_database [raw->sub_type].minimum_efficiency < 1.0);

		// the following is currently required for the campaign to progress properly...
		ASSERT (keysite_database [raw->sub_type].repairable == keysite_database [raw->sub_type].troop_insertion_target);

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

		update_keysite_cargo (en, raw->supplies.ammo_supply_level, ENTITY_SUB_TYPE_CARGO_AMMO, CARGO_AMMO_SIZE);

		update_keysite_cargo (en, raw->supplies.fuel_supply_level, ENTITY_SUB_TYPE_CARGO_FUEL, CARGO_FUEL_SIZE);

		////////////////////////////////////////
		//
		// BUILD COMPONENTS
		//
		////////////////////////////////////////

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

		force = get_local_entity_parent (en, LIST_TYPE_KEYSITE_FORCE);

		debug_assert (get_local_entity_type (force) == ENTITY_TYPE_FORCE);

		ASSERT (force);

		sector = get_local_sector_entity (&raw->position);

		ASSERT (sector);

		insert_local_entity_into_parents_child_list (en, LIST_TYPE_KEYSITE_FORCE, force, NULL);

		insert_local_entity_into_parents_child_list (en, LIST_TYPE_SECTOR, sector, NULL);

		insert_local_entity_into_parents_child_list (en, LIST_TYPE_UPDATE, get_update_entity (), NULL);

		set_local_entity_int_value (sector, INT_TYPE_KEYSITE_COUNT, get_local_entity_int_value (sector, INT_TYPE_KEYSITE_COUNT) + 1);

		if (raw->in_use)
		{
			update_imap_sector_side (en, TRUE);

			update_imap_importance_level (en, TRUE);

			update_keysite_distance_to_friendly_base (en, raw->side);
		}

		////////////////////////////////////////
		//
		//	CREATE SUB ENTITIES
		//
		////////////////////////////////////////

		// for site buildings

		group = create_local_entity
		(
			ENTITY_TYPE_GROUP,
			ENTITY_INDEX_DONT_CARE,
			ENTITY_ATTR_PARENT (LIST_TYPE_BUILDING_GROUP, en),
			ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, raw->position.x, raw->position.y, raw->position.z),
			ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, ENTITY_SUB_TYPE_GROUP_BUILDINGS),
			ENTITY_ATTR_END
		);

		#if DEBUG_MODULE
		{
			int
				sx,
				sz;

			get_x_sector (sx, raw->position.x);
			get_z_sector (sz, raw->position.z);
			
			debug_log ("KS_CREAT: Side %s creating keysite %s (type %d) index %d at %f, %f (%d, %d)", entity_side_short_names [raw->side], raw->keysite_name, raw->sub_type, get_local_entity_index (en), raw->position.x, raw->position.z, sx, sz);
		}
		#endif
	}

	return (en);
}
Beispiel #6
0
entity *create_local_sound_effect_entity
			(
				int index,
				entity *parent,
				entity_sides side,
				entity_sub_types sub_type,
				sound_channel_types channel,
				sound_locality_types locality,
				vec3d *position,
				float amp,
				int valid,
				int looping,
				int sample_count,
				sound_sample_indices *sample_indices
			)
{
	entity
		*en;

	vec3d
		pos;

	int
		panning,
		create_stack_attributes;

	ASSERT (parent);

	create_stack_attributes = force_local_entity_create_stack_attributes;

	if (get_comms_data_flow () == COMMS_DATA_FLOW_RX)
	{
		set_force_local_entity_create_stack_attributes (TRUE);
	}

	panning = TRUE;

	if (position)
	{
		pos = *position;
	}
	else
	{
		position = get_local_entity_vec3d_ptr (parent, VEC3D_TYPE_POSITION);

		if (position)
		{
			pos = *position;
		}
		else
		{
			pos.x = MID_MAP_X;
			pos.y = MID_MAP_Y;
			pos.z = MID_MAP_Z;

			panning = FALSE;
		}
	}

	//
	// special cases for speech
	//
	
	switch (sub_type)
	{
		case ENTITY_SUB_TYPE_EFFECT_SOUND_RADIO_MESSAGE:
		{
			if (get_global_gunship_side () == side)
			{
				amp = adjust_radio_message_amplification (amp, &pos);
			}
			else
			{	
				amp = 0.0;
			}

			panning = FALSE;

			break;
		}

		case ENTITY_SUB_TYPE_EFFECT_SOUND_CPG_MESSAGE:
		case ENTITY_SUB_TYPE_EFFECT_SOUND_WARNING_MESSAGE:
		{
			if (parent == get_gunship_entity ())
			{
				amp = 1.0;
			}
			else
			{
				amp = 0.0;
			}

			panning = FALSE;

			break;
		}
	}

	//
	// create sound
	//

	en = create_local_entity
	(
		ENTITY_TYPE_SOUND_EFFECT,
		index,
		ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, sub_type),
		ENTITY_ATTR_PARENT (LIST_TYPE_SPECIAL_EFFECT, parent),
		ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, pos.x, pos.y, pos.z),
		ENTITY_ATTR_INT_VALUE (INT_TYPE_SOUND_CHANNEL, channel),
		ENTITY_ATTR_INT_VALUE (INT_TYPE_SOUND_EFFECT_LOOPING, looping),
		ENTITY_ATTR_INT_VALUE (INT_TYPE_SOUND_EFFECT_PANNING, panning),
		ENTITY_ATTR_INT_VALUE (INT_TYPE_SOUND_LOCALITY, locality),
		ENTITY_ATTR_INT_VALUE (INT_TYPE_VALID_SOUND_EFFECT, valid),
		ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_AMPLIFICATION, amp),
		ENTITY_ATTR_END
	);

	set_local_sound_effect_sample_indices (en, sample_count, sample_indices);

	#if DEBUG_MODULE

	debug_log ("SOUNDEFF : created effect %s (%d), parent %s (%d), next %d, looping %d, valid %d",
							application_sound_effects [sample_indices [0]].name,
							get_local_entity_index (en),
							get_local_entity_type_name (parent),
							get_local_entity_index (parent),
							looping,
							valid);

	#endif

	set_force_local_entity_create_stack_attributes (create_stack_attributes);

	return en;
}
Beispiel #7
0
static int load_local_pylon_entities (char *name)
{
	entity
		*last_entity,
		*last_last_entity,
		*new_entity;

	entity_sub_types
		sub_type;

	int
		type,
		node_count,
		*node_link_count,
		path_count,
		node_loop,
		path_loop,
		start,
		end,
		link_count,
		link_loop;

	vec3d
		*node_positions,
		pos;

	FILE
		*pylon_node_file_ptr,
		*pylon_link_file_ptr;

	char
		filename [1024];

	session_list_data_type
		*current_session;

	//
	// Create "Node" Pylons
	//

	ASSERT (get_valid_current_game_session ());

	ASSERT (name);

	current_session = get_current_game_session ();

	sprintf (filename, "%s//route//%s.nde", current_session->data_path, name);

	if (file_exist (filename))
	{
		pylon_node_file_ptr = safe_fopen (filename, "rb");

		fread (&node_count, sizeof (int), 1, pylon_node_file_ptr);

		node_positions = malloc_heap_mem (sizeof (vec3d) * node_count);

		node_link_count = malloc_heap_mem (sizeof (int) * node_count);

		for (node_loop = 0 ; node_loop < node_count ; node_loop ++)
		{
			fread (&pos, sizeof (vec3d), 1, pylon_node_file_ptr);

			node_positions [node_loop].x = pos.x;
			node_positions [node_loop].y = pos.y;
			node_positions [node_loop].z = pos.z;

			node_link_count [node_loop] = 0;
		}

		fclose (pylon_node_file_ptr);

		//
		// Create "Link" Pylons
		//

		sprintf (filename, "%s//route//%s.wp", current_session->data_path, name);

		pylon_link_file_ptr = safe_fopen (filename, "rb");

		fread (&path_count, sizeof (int), 1, pylon_link_file_ptr);

		new_entity = NULL;

		for (path_loop = 0 ; path_loop < path_count ; path_loop ++)
		{
			fread (&start, sizeof (int), 1, pylon_link_file_ptr);

			fread (&end, sizeof (int), 1, pylon_link_file_ptr);

			fread (&type, sizeof (int), 1, pylon_link_file_ptr);

			fread (&link_count, sizeof (int), 1, pylon_link_file_ptr);

			node_link_count [start] += 1;
			node_link_count [end] += 1;

			if (link_count > 0)
			{
				last_entity = NULL;

				last_last_entity = NULL;

				for (link_loop = 0 ; link_loop < link_count ; link_loop ++)
				{
					fread (&pos, sizeof (vec3d), 1, pylon_link_file_ptr);

					if (link_loop == 0)
					{
						sub_type = ENTITY_SUB_TYPE_FIXED_ELECTRICITY_PYLON_START_TERMINATOR;
					}
					else if (link_loop == link_count - 1)
					{
						sub_type = ENTITY_SUB_TYPE_FIXED_ELECTRICITY_PYLON_END_TERMINATOR;
					}
					else
					{
						sub_type = ENTITY_SUB_TYPE_FIXED_ELECTRICITY_PYLON_STANDARD;
					}

					new_entity = create_local_entity
					(
						ENTITY_TYPE_PYLON,
						ENTITY_INDEX_DONT_CARE,
						ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, sub_type),
						ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, pos.x, pos.y, pos.z),
						ENTITY_ATTR_FLOAT_VALUE (FLOAT_TYPE_HEADING, 0),
						ENTITY_ATTR_PTR_VALUE (PTR_TYPE_SUCC, last_entity),
						ENTITY_ATTR_END
					);

					calculate_pylon_heading (last_last_entity, last_entity, new_entity, &node_positions [start], &node_positions [end]);

					last_last_entity = last_entity;

					last_entity = new_entity;
				}

				// last pylon in the link
				calculate_pylon_heading (last_last_entity, last_entity, NULL, &node_positions [start], &node_positions [end]);
			}
		}

		for (node_loop = 0 ; node_loop < node_count ; node_loop ++)
		{
			//
			// create node entities here
			//
		}

		fclose (pylon_link_file_ptr);

		free_mem (node_positions);

		free_mem (node_link_count);

		return TRUE;
	}

	return FALSE;
}
Beispiel #8
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;
}
Beispiel #9
0
void create_client_server_entity_weapon (entity *launcher, entity_sub_types weapon_sub_type, int weapon_index, int burst_size, int *smoke_trail_indices)
{
	entity
		*force,
		*target,
		*weapon;

	meta_smoke_list_types
		smoke_trail_type;

	int
		i,
		num_smoke_trail_entities,
		valid_sound_effect,
		current_weapon_count,
		new_weapon_count;

	ASSERT (launcher);

	ASSERT (entity_sub_type_weapon_valid (weapon_sub_type));

	//
	// get target
	//

	if (!(weapon_database[weapon_sub_type].weapon_class & (WEAPON_CLASS_DECOY | WEAPON_CLASS_CARGO | WEAPON_CLASS_DEBRIS)))
	{
		target = get_local_entity_parent (launcher, LIST_TYPE_TARGET);

/*		if (weapon_database[weapon_sub_type].hellfire_flight_profile)
		{
			if (get_local_entity_int_value (launcher, INT_TYPE_LOCK_ON_AFTER_LAUNCH))
			{
				target = NULL;
			}
		} */
	}
	else
	{
		target = NULL;
	}

	if (get_comms_model () == COMMS_MODEL_SERVER)
	{
		////////////////////////////////////////
		//
		// SERVER/TX and SERVER/RX
		//
		////////////////////////////////////////

		ASSERT (weapon_index == ENTITY_INDEX_DONT_CARE);

		ASSERT (burst_size == BURST_SIZE_DONT_CARE);

		ASSERT (!smoke_trail_indices);

		// NOTE: The clients' weapon counters lag the servers' so it is possible that the
		//       client may unknowingly attempt to create more weapons than are available.
		//       This is prone to happen during rapid firing.

		current_weapon_count = get_local_entity_weapon_count (launcher, weapon_sub_type);

		if (current_weapon_count > 0)
		{
			int loal_mode = weapon_database[weapon_sub_type].hellfire_flight_profile && get_local_entity_int_value (launcher, INT_TYPE_LOCK_ON_AFTER_LAUNCH);

			if (get_comms_data_flow () == COMMS_DATA_FLOW_RX)
			{
				set_force_local_entity_create_stack_attributes (TRUE);
			}

			//
			// get burst size wrt rate of fire
			//

			if (weapon_database[weapon_sub_type].rate_of_fire != FIRE_SINGLE_WEAPON)
			{
				float time_per_shot = weapon_database[weapon_sub_type].inverse_rate_of_fire * ONE_MINUTE;
				unsigned int* last_shot = NULL;

				switch (launcher->type)
				{
				case ENTITY_TYPE_HELICOPTER:
					last_shot = &((helicopter*)get_local_entity_data(launcher))->ac.weapon_salvo_timer;
					break;

				case ENTITY_TYPE_FIXED_WING:
					last_shot = &((fixed_wing*)get_local_entity_data(launcher))->ac.weapon_salvo_timer;
					break;

				case ENTITY_TYPE_ANTI_AIRCRAFT:
					last_shot = &((anti_aircraft*)get_local_entity_data(launcher))->vh.weapon_salvo_timer;
					break;

				case ENTITY_TYPE_PERSON:
					last_shot = &((person*)get_local_entity_data(launcher))->vh.weapon_salvo_timer;
					break;

				case ENTITY_TYPE_ROUTED_VEHICLE:
					last_shot = &((routed_vehicle*)get_local_entity_data(launcher))->vh.weapon_salvo_timer;
					break;

				case ENTITY_TYPE_SHIP_VEHICLE:
					last_shot = &((ship_vehicle*)get_local_entity_data(launcher))->vh.weapon_salvo_timer;
					break;
				}

				if (last_shot)
				{
					unsigned int current_time = get_system_time();
					float elapsed_time = 1;

					if (*last_shot > 0)
					{
						if (current_time < *last_shot)
							return;
						elapsed_time = (current_time - *last_shot) * 0.001;
					}
					else
						elapsed_time = get_delta_time();

					burst_size = (int)(weapon_database[weapon_sub_type].rate_of_fire * ONE_OVER_ONE_MINUTE * elapsed_time);
					if (burst_size < 1)
					{
						if (*last_shot == 0)  // first shot in salvo always get fired
							burst_size = 1;
						else
							return;
					}

					if (*last_shot)
						*last_shot += (int)(burst_size * time_per_shot * 1000.0);
					else
						*last_shot = current_time;
				}
				else
				{
					ASSERT(FALSE);
					burst_size = 1;
				}
			}
			else
			{
				burst_size = 1;
			}

			//
			// set burst timer
			//

			valid_sound_effect = FALSE;

			if (get_local_entity_float_value (launcher, FLOAT_TYPE_WEAPON_BURST_TIMER) == 0.0)
			{
				set_local_entity_float_value (launcher, FLOAT_TYPE_WEAPON_BURST_TIMER, weapon_database[weapon_sub_type].burst_duration);

				valid_sound_effect = TRUE;
			}

			//
			// create weapon
			//

			weapon = create_local_entity
			(
				ENTITY_TYPE_WEAPON,
				ENTITY_INDEX_DONT_CARE,
				ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, weapon_sub_type),
				ENTITY_ATTR_INT_VALUE (INT_TYPE_WEAPON_BURST_SIZE, burst_size),
				ENTITY_ATTR_INT_VALUE (INT_TYPE_WEAPON_MISSILE_PHASE, MISSILE_PHASE1),
				ENTITY_ATTR_INT_VALUE (INT_TYPE_LOCK_ON_AFTER_LAUNCH, loal_mode),
				ENTITY_ATTR_PARENT (LIST_TYPE_LAUNCHED_WEAPON, launcher),
				ENTITY_ATTR_PARENT (LIST_TYPE_TARGET, target),
				ENTITY_ATTR_END
			);

			if (weapon)
			{
				//
				// send FIRE message to force (unless it's a decoy/cargo/debris being launched)
				//

				if ((target) && (!(weapon_database[weapon_sub_type].weapon_class & (WEAPON_CLASS_DECOY | WEAPON_CLASS_CARGO | WEAPON_CLASS_DEBRIS))))
				{
					force = get_local_force_entity ((entity_sides) get_local_entity_int_value (target, INT_TYPE_SIDE));

					if (force)
					{
						notify_local_entity (ENTITY_MESSAGE_ENTITY_FIRED_AT, force, launcher, target);
					}
				}

				//
				// create sound effect(s)
				//

				if (valid_sound_effect)
				{
					create_weapon_launched_sound_effects (launcher, weapon_sub_type);
				}

				//
				// create smoke trail
				//

				smoke_trail_type = (meta_smoke_list_types) get_local_entity_int_value (weapon, INT_TYPE_WEAPON_SMOKE_TRAIL_TYPE);

				if (smoke_trail_type != META_SMOKE_LIST_TYPE_NONE)
				{
					struct OBJECT_3D_BOUNDS
						*bounding_box;

					vec3d
						exhaust_offset;

					num_smoke_trail_entities = count_entities_in_meta_smoke_list (smoke_trail_type);

					ASSERT (num_smoke_trail_entities > 0);

					smoke_trail_indices = (int *) malloc_fast_mem (sizeof (int) * num_smoke_trail_entities);

					for (i = 0; i < num_smoke_trail_entities; i++)
					{
						smoke_trail_indices[i] = ENTITY_INDEX_DONT_CARE;
					}

					bounding_box = get_object_3d_bounding_box (get_local_entity_int_value (weapon, INT_TYPE_DEFAULT_3D_SHAPE));

					if ((weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_PILOT) ||(weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_CO_PILOT))
					{
						exhaust_offset.x = 0.0;
						exhaust_offset.y = 0.0;
						exhaust_offset.z = 0.0;
					}
					else
					{
						exhaust_offset.x = 0.0;
						exhaust_offset.y = 0.0;
						exhaust_offset.z = bounding_box->zmin;
					}

					create_meta_smoke_list_specified_offset (smoke_trail_type, weapon, &exhaust_offset, smoke_trail_indices);
				}

				transmit_entity_comms_message
				(
					ENTITY_COMMS_CREATE_WEAPON,
					NULL,
					launcher,
					weapon_sub_type,
					get_local_entity_safe_index (weapon),
					burst_size,
					smoke_trail_indices
				);

				if (smoke_trail_indices)
				{
					free_mem (smoke_trail_indices);
				}

				//
				// out of weapons (if infinite weapons then reload else select next weapon)
				//

				new_weapon_count = get_local_entity_weapon_count (launcher, weapon_sub_type);

				if (new_weapon_count <= 0)
				{
					#if !DEMO_VERSION
					if (get_local_entity_int_value (get_session_entity (), INT_TYPE_INFINITE_WEAPONS))
					{
						weapon_config_types
							config_type;

						config_type = (weapon_config_types) get_local_entity_int_value (launcher, INT_TYPE_WEAPON_CONFIG_TYPE);

						set_client_server_entity_int_value (launcher, INT_TYPE_WEAPON_CONFIG_TYPE, config_type);
					}
					else
					#endif
					{
						//
						// play weapon out of ammo speech
						//

						play_entity_weapon_out_speech (launcher, weapon_sub_type);

						//
						// select next weapon
						//
/*
						if (!(weapon_database[weapon_sub_type].weapon_class & (WEAPON_CLASS_DECOY | WEAPON_CLASS_CARGO | WEAPON_CLASS_DEBRIS)))
						{
							entity_sub_types
								next_weapon_sub_type;

							if (get_local_entity_int_value (launcher, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI)
							{
								next_weapon_sub_type = get_next_available_weapon_sub_type (launcher);
							}
							else
							{
								next_weapon_sub_type = ENTITY_SUB_TYPE_WEAPON_NO_WEAPON;
							}

							set_client_server_entity_int_value (launcher, INT_TYPE_SELECTED_WEAPON, next_weapon_sub_type);
						}
*/
					}
				}
				else
				{
					int
						report_ammo_low_count;

					report_ammo_low_count = weapon_database[weapon_sub_type].report_ammo_low_count;

					if ((current_weapon_count > report_ammo_low_count) && (new_weapon_count <= report_ammo_low_count))
					{
						//
						// play weapon low speech
						//

						play_entity_weapon_low_speech (launcher, weapon_sub_type);
					}
					else
					{
						//
						// weapon launch speech
						//

						play_entity_weapon_launched_speech (launcher, weapon_sub_type);
					}
				}
			}

			set_force_local_entity_create_stack_attributes (FALSE);
		}
		else
		{
			pause_client_server_continuous_weapon_sound_effect (launcher, weapon_sub_type);
		}
	}
	else
	{
		if (get_comms_data_flow () == COMMS_DATA_FLOW_TX)
		{
			////////////////////////////////////////
			//
			// CLIENT/TX
			//
			////////////////////////////////////////

			ASSERT (weapon_index == ENTITY_INDEX_DONT_CARE);

			ASSERT (burst_size == BURST_SIZE_DONT_CARE);

			ASSERT (!smoke_trail_indices);

			// NOTE: The clients' weapon counters lag the servers' so it is possible that the
			//       client may unknowingly attempt to create more weapons than are available.
			//       This is prone to happen during rapid firing.

			if (get_local_entity_weapon_available (launcher, weapon_sub_type))
			{
				transmit_entity_comms_message
				(
					ENTITY_COMMS_CREATE_WEAPON,
					NULL,
					launcher,
					weapon_sub_type,
					ENTITY_INDEX_DONT_CARE,
					burst_size,
					NULL
				);
			}
		}
		else
		{
			////////////////////////////////////////
			//
			// CLIENT/RX
			//
			////////////////////////////////////////

			ASSERT (weapon_index != ENTITY_INDEX_DONT_CARE);

			ASSERT (burst_size > 0);

			set_force_local_entity_create_stack_attributes (TRUE);

			weapon = create_local_entity
			(
				ENTITY_TYPE_WEAPON,
				weapon_index,
				ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, weapon_sub_type),
				ENTITY_ATTR_INT_VALUE (INT_TYPE_WEAPON_BURST_SIZE, burst_size),
				ENTITY_ATTR_PARENT (LIST_TYPE_LAUNCHED_WEAPON, launcher),
				ENTITY_ATTR_PARENT (LIST_TYPE_TARGET, target),
				ENTITY_ATTR_END
			);

			ASSERT (weapon);

			//
			// create smoke trail
			//

			smoke_trail_type = (meta_smoke_list_types) get_local_entity_int_value (weapon, INT_TYPE_WEAPON_SMOKE_TRAIL_TYPE);

			if (smoke_trail_type != META_SMOKE_LIST_TYPE_NONE)
			{
				struct OBJECT_3D_BOUNDS
					*bounding_box;

				vec3d
					exhaust_offset;

				ASSERT (smoke_trail_indices);

				bounding_box = get_object_3d_bounding_box (get_local_entity_int_value (weapon, INT_TYPE_DEFAULT_3D_SHAPE));

				if ((weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_PILOT) ||(weapon_sub_type == ENTITY_SUB_TYPE_WEAPON_HOKUM_CO_PILOT))
				{
					exhaust_offset.x = 0.0;
					exhaust_offset.y = 0.0;
					exhaust_offset.z = 0.0;
				}
				else
				{
					exhaust_offset.x = 0.0;
					exhaust_offset.y = 0.0;
					exhaust_offset.z = bounding_box->zmin;
				}

				create_meta_smoke_list_specified_offset (smoke_trail_type, weapon, &exhaust_offset, smoke_trail_indices);
			}
			else
			{
				ASSERT (!smoke_trail_indices);
			}

			set_force_local_entity_create_stack_attributes (FALSE);
		}
	}
}
Beispiel #10
0
entity *create_client_server_entity_fixed_wing (int index, entity_sub_types sub_type, entity *group, vec3d *position)
{
	entity
		*new_entity;

	fixed_wing
		*raw;

	ASSERT (get_comms_model() == COMMS_MODEL_SERVER);

	//
	// create fixed wing entity
	//

	new_entity = create_client_server_entity
	(
		ENTITY_TYPE_FIXED_WING,
		index,
		ENTITY_ATTR_PARENT (LIST_TYPE_MEMBER, group),
		ENTITY_ATTR_INT_VALUE (INT_TYPE_ENTITY_SUB_TYPE, sub_type),
		ENTITY_ATTR_VEC3D (VEC3D_TYPE_POSITION, position->x, position->y, position->z),
		ENTITY_ATTR_END
	);

	//
	// create and attach special effects
	//

	{
		sound_sample_indices
			sound_sample_index;

		//
		// damage smoke
		//

		attach_fixed_wing_meta_smoke_lists (new_entity);

		//
		// sound effects
		//

		sound_sample_index = aircraft_database [sub_type].continuous_sound_effect_index;

		create_client_server_sound_effect_entity
		(
			new_entity,
			ENTITY_SIDE_NEUTRAL,
			ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING1,
			SOUND_CHANNEL_SOUND_EFFECT,
			SOUND_LOCALITY_ALL,
			NULL,												// position
			1.0,												// amplification
			FALSE,											// valid sound effect
			TRUE,												// looping
			1,													// sample count
			&sound_sample_index							// sample index list
		);

		sound_sample_index = SOUND_SAMPLE_INDEX_JET_AFTERBURNER;

		create_client_server_sound_effect_entity
		(
			new_entity,
			ENTITY_SIDE_NEUTRAL,
			ENTITY_SUB_TYPE_EFFECT_SOUND_ENGINE_LOOPING2,
			SOUND_CHANNEL_SOUND_EFFECT,
			SOUND_LOCALITY_ALL,
			NULL,												// position
			1.0,												// amplification
			FALSE,											// valid sound effect
			TRUE,												// looping
			1,													// sample count
			&sound_sample_index							// sample index list
		);
	}

	//
	// initialise terrain elevation cache
	//

	raw = get_local_entity_data (new_entity);

	get_3d_terrain_point_data (position->x, position->z, &raw->ac.terrain_info);

	return new_entity;
}
Beispiel #11
0
void create_local_sector_entities (void)
{
	static int
		old_min_map_z_sector = -1,
		old_max_map_z_sector = -1,
		old_num_map_z_sectors = -1,
		old_min_map_x_sector = -1,
		old_max_map_x_sector = -1,
		old_num_map_x_sectors = -1;

	int
		x_sec,
		z_sec;

	//
	// First time setup
	//

	if (old_min_map_z_sector == -1)
	{
		old_min_map_z_sector = MIN_MAP_Z_SECTOR;

		old_max_map_z_sector = MAX_MAP_Z_SECTOR;

		old_num_map_z_sectors = NUM_MAP_Z_SECTORS;

		old_min_map_x_sector = MIN_MAP_X_SECTOR;

		old_max_map_x_sector = MAX_MAP_X_SECTOR;

		old_num_map_x_sectors = NUM_MAP_X_SECTORS;
	}

	//
	// Deinitialise sectors (must be the 'old' map size)
	//

	if (entity_sector_map)
	{
		for (z_sec = old_min_map_z_sector; z_sec <= old_max_map_z_sector; z_sec ++)
		{
			for (x_sec = old_min_map_x_sector; x_sec <= old_max_map_x_sector; x_sec ++)
			{
				if (entity_sector_map [x_sec + (z_sec * old_num_map_x_sectors)]->type != ENTITY_TYPE_UNKNOWN)
				{
					debug_fatal ("SC_CREAT: uninitialised sector entity");
				}
			}
		}

		free_mem (entity_sector_map);
	}

	//
	// Store new map size
	//

	old_min_map_z_sector = MIN_MAP_Z_SECTOR;

	old_max_map_z_sector = MAX_MAP_Z_SECTOR;

	old_num_map_z_sectors = NUM_MAP_Z_SECTORS;

	old_min_map_x_sector = MIN_MAP_X_SECTOR;

	old_max_map_x_sector = MAX_MAP_X_SECTOR;

	old_num_map_x_sectors = NUM_MAP_X_SECTORS;

	//
	// Malloc memory
	//

	entity_sector_map = (entity **) malloc_heap_mem (sizeof (entity) * NUM_MAP_X_SECTORS * NUM_MAP_Z_SECTORS);

	//
	// Create sector entities
	//

	for (z_sec = MIN_MAP_Z_SECTOR; z_sec <= MAX_MAP_Z_SECTOR; z_sec++)
	{
		for (x_sec = MIN_MAP_X_SECTOR; x_sec <= MAX_MAP_X_SECTOR; x_sec++)
		{
			entity_sector_map[x_sec + (z_sec * NUM_MAP_X_SECTORS)] = create_local_entity
			(
				ENTITY_TYPE_SECTOR,
				ENTITY_INDEX_DONT_CARE,
				ENTITY_ATTR_INT_VALUE (INT_TYPE_X_SECTOR, x_sec),
				ENTITY_ATTR_INT_VALUE (INT_TYPE_Z_SECTOR, z_sec),
				ENTITY_ATTR_END
			);
		}
	}

	debug_log ("SC_CREAT: creating sectors. Start entity %d", get_local_entity_index (entity_sector_map [0]));
}