Beispiel #1
0
int get_angle_of_projection (const vec3d *source, const vec3d *target, float velocity, float *angle_of_projection)
{
	if (velocity > 0.001)
	{
		float range = get_2d_range (source, target);
		return get_angle_of_projection_with_range(source, target, velocity, angle_of_projection, range);
	}
	else
		return FALSE;
}
Beispiel #2
0
void update_waypoint_shared_mem()
{
	entity* wp;

	if (!gPtrSharedMemory || !get_gunship_entity())
		return;

	wp = get_local_entity_current_waypoint(get_gunship_entity());

	if (wp)
	{
		vec3d
			*gunship_position,
			waypoint_position;

		float
			dx,
			dz,
			bearing;

		gunship_position = get_local_entity_vec3d_ptr(get_gunship_entity(), VEC3D_TYPE_POSITION);
		get_waypoint_display_position (get_gunship_entity(), wp, &waypoint_position);

		gPtrSharedMemory->waypoint_data.waypoint = get_local_entity_char_value(wp, CHAR_TYPE_TAG);
		gPtrSharedMemory->waypoint_data.waypoint_range = get_2d_range (gunship_position, &waypoint_position);

		dx = waypoint_position.x - gunship_position->x;
		dz = waypoint_position.z - gunship_position->z;

		bearing = deg(atan2(dx, dz));
		if (bearing < 0.0)
			bearing += 360.0;

		gPtrSharedMemory->waypoint_data.waypoint_bearing = bearing;
	}
	else
		memset(&gPtrSharedMemory->waypoint_data, 0, sizeof(waypoint_data_t));
}
Beispiel #3
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;
}
Beispiel #4
0
void group_return_to_base (entity *en)
{

	entity
		*wp,
		*guide,
		*last_wp,
		*best_wp,
		*obj_wp,
		*current_wp;

	vec3d
		*pos,
		*wp_pos,
		*last_pos,
		normal;

	float
		d,
		range,
		best_range;

	int
		s,
		sub_type;

	debug_log ("GROUP: sending group %s (%d) home... ", get_local_entity_string (en, STRING_TYPE_FULL_NAME), get_local_entity_index (en));

	//
	// Abort all engage tasks
	//

	terminate_all_engage_tasks (en);

	//
	// Find group position
	//

	pos = get_local_entity_vec3d_ptr (en, VEC3D_TYPE_POSITION);

	//
	// find objective wp, and last wp position
	//

	obj_wp = NULL;

	guide = get_local_group_primary_guide (en);

	ASSERT (guide);

	current_wp = get_local_entity_parent (guide, LIST_TYPE_CURRENT_WAYPOINT);

	ASSERT (current_wp);

	wp = current_wp;

	while (get_local_entity_child_succ (wp, LIST_TYPE_WAYPOINT))
	{
		wp = get_local_entity_child_succ (wp, LIST_TYPE_WAYPOINT);

		sub_type = get_local_entity_int_value (wp, INT_TYPE_ENTITY_SUB_TYPE);

		if (waypoint_database [sub_type].objective_waypoint)
		{
			obj_wp = wp;
		}
	}

	last_wp = wp;

	last_pos = get_local_entity_vec3d_ptr (last_wp, VEC3D_TYPE_POSITION);

	if (current_wp == last_wp)
	{
		return;
	}

	//
	// Check each waypoint after the objective waypoint (if obj_wp is NULL then the group has already passed the objective wp
	//		or there isn't one)
	//

	if (!obj_wp)
	{
		obj_wp = current_wp;
	}

	//
	// Find vector of group to last wp
	//

	normal.x = last_pos->x - pos->x;
	normal.y = 0.0;
	normal.z = last_pos->z - pos->z;

	if (normalise_any_3d_vector (&normal) == 0.0)
	{
		return;
	}

	//
	// Test sign of last position
	//

	d = ((last_pos->x * normal.x) + (last_pos->z * normal.z)) - ((pos->x * normal.x) + (pos->z * normal.z));

	s = sign (d);

	//
	// find closest waypoint heading back towards the last waypoint
	//

	wp = get_local_entity_child_succ (obj_wp, LIST_TYPE_WAYPOINT);

	ASSERT (wp);

	best_wp = last_wp;

	best_range = FLT_MAX;

	while (wp)
	{
		wp_pos = get_local_entity_vec3d_ptr (wp, VEC3D_TYPE_POSITION);

		d = ((wp_pos->x * normal.x) + (wp_pos->z * normal.z)) - ((pos->x * normal.x) + (pos->z * normal.z));

		if (sign (d) == s)
		{
			range = get_2d_range (wp_pos, pos);

			if (range < best_range)
			{
				best_wp = wp;

				best_range = range;
			}
		}

		wp = get_local_entity_child_succ (wp, LIST_TYPE_WAYPOINT);
	}

	//
	// set guide to best waypoint
	//

	set_guide_new_waypoint (guide, best_wp);
}
Beispiel #5
0
int amalgamate_groups (entity *receiving_group, entity *donating_group)
{

	entity
		*this_member,
		*member;

	int
		group_type,
		group_kills,
		group_losses,
		donating_group_count,
		receiving_group_count;

	ASSERT (get_comms_model () == COMMS_MODEL_SERVER);

	// check both groups are not doing any tasks

	ASSERT (get_local_entity_int_value (receiving_group, INT_TYPE_GROUP_MODE) == GROUP_MODE_IDLE);

	ASSERT (get_local_entity_int_value (donating_group, INT_TYPE_GROUP_MODE) == GROUP_MODE_IDLE);

	// check group type are the same

	group_type = get_local_entity_int_value (receiving_group, INT_TYPE_ENTITY_SUB_TYPE);

	if (group_type != get_local_entity_int_value (donating_group, INT_TYPE_ENTITY_SUB_TYPE))
	{
		return FALSE;
	}

	ASSERT (group_database [group_type].amalgamate);

	ASSERT (get_local_entity_int_value (donating_group, INT_TYPE_SIDE) == get_local_entity_int_value (receiving_group, INT_TYPE_SIDE));

	donating_group_count = get_local_entity_int_value (donating_group, INT_TYPE_MEMBER_COUNT);

	receiving_group_count = get_local_entity_int_value (receiving_group, INT_TYPE_MEMBER_COUNT);

	if ((donating_group_count + receiving_group_count) <= group_database [group_type].maximum_member_count)
	{

		#ifdef DEBUG

		//#if DEBUG_MODULE

		if ((get_local_entity_parent (donating_group, LIST_TYPE_KEYSITE_GROUP)) && (get_local_entity_parent (receiving_group, LIST_TYPE_KEYSITE_GROUP)))
		{

			ASSERT (get_local_entity_type (get_local_entity_parent (donating_group, LIST_TYPE_KEYSITE_GROUP)) == get_local_entity_type (get_local_entity_parent (receiving_group, LIST_TYPE_KEYSITE_GROUP)));
		}

		debug_log ("GROUP: amalgamating group %s %d (count %d) with group %s %d (count %d)",
							entity_sub_type_group_names [group_type], get_local_entity_index (donating_group), donating_group_count,
							entity_sub_type_group_names [group_type], get_local_entity_index (receiving_group), receiving_group_count);

		member = get_local_entity_first_child (donating_group, LIST_TYPE_MEMBER);

		while (member)
		{

			debug_log ("GROUP:	donating group member %s (%d)", get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member));

			ASSERT (get_local_entity_int_value (member, INT_TYPE_OPERATIONAL_STATE) == OPERATIONAL_STATE_LANDED);

			member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER);
		}

		member = get_local_entity_first_child (receiving_group, LIST_TYPE_MEMBER);

		while (member)
		{

			debug_log ("GROUP:	receiving group member %s (%d)", get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member));

			ASSERT (get_local_entity_int_value (member, INT_TYPE_OPERATIONAL_STATE) == OPERATIONAL_STATE_LANDED);

			member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER);
		}

		//#endif

		#endif

		member = get_local_entity_first_child (donating_group, LIST_TYPE_MEMBER);

		while (member)
		{

			this_member = member;

			member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER);

			set_client_server_entity_parent (this_member, LIST_TYPE_MEMBER, receiving_group);
		}

		group_kills = get_local_entity_int_value (receiving_group, INT_TYPE_KILLS);
		group_losses = get_local_entity_int_value (receiving_group, INT_TYPE_LOSSES);

		group_kills += get_local_entity_int_value (donating_group, INT_TYPE_KILLS);
		group_losses += get_local_entity_int_value (donating_group, INT_TYPE_LOSSES);

		if (get_local_entity_int_value (receiving_group, INT_TYPE_KILLS) != group_kills)
		{

			set_client_server_entity_int_value (receiving_group, INT_TYPE_KILLS, group_kills);
		}

		if (get_local_entity_int_value (receiving_group, INT_TYPE_LOSSES) != group_losses)
		{

			set_client_server_entity_int_value (receiving_group, INT_TYPE_LOSSES, group_losses);
		}

		//
		// renumber the group members
		//

		set_group_member_numbers (receiving_group);

		//
		// place empty donating group on free list
		//

		ASSERT (get_local_entity_int_value (donating_group, INT_TYPE_MEMBER_COUNT) == 0);

		kill_client_server_group_entity (donating_group);

		#ifdef DEBUG
		{

			vec3d
				*pos1,
				*test_pos;

			float
				amalgamate_max_range = 10 * KILOMETRE;

			member = get_local_entity_first_child (receiving_group, LIST_TYPE_MEMBER);

			ASSERT (member);
	
			pos1 = get_local_entity_vec3d_ptr (member, VEC3D_TYPE_POSITION);
	
			member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER);

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

				if (get_2d_range (pos1, test_pos) > amalgamate_max_range)
				{

					debug_log ("GROUP: WARNING: Amalgamated group with members (%s (%d) and %s (%d)) %f apart -------------------------",
									get_local_entity_string (get_local_entity_first_child (receiving_group, LIST_TYPE_MEMBER), STRING_TYPE_FULL_NAME),
									get_local_entity_index (get_local_entity_first_child (receiving_group, LIST_TYPE_MEMBER)),
									get_local_entity_string (member, STRING_TYPE_FULL_NAME),
									get_local_entity_index (member),
									get_2d_range (pos1, test_pos));
				}

				member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER);
			}
	
		}
		#endif

		return TRUE;
	}

	return FALSE;
}
Beispiel #6
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);
}
Beispiel #7
0
entity *get_closest_waypoint (entity *task, vec3d *pos, float min_range, float *actual_range)
{

	float
		best_range,
		range;

	vec3d
		*waypoint_pos;

	entity
		*closest_waypoint = NULL,
		*current_waypoint;

	best_range = 99999999;

	current_waypoint = get_local_entity_first_child (task, LIST_TYPE_WAYPOINT);

	while (current_waypoint)
	{

		waypoint_pos = get_local_entity_vec3d_ptr (current_waypoint, VEC3D_TYPE_POSITION);

		range = get_approx_2d_range (waypoint_pos, pos);

		if (actual_range)
		{
	
			*actual_range = range;
		}

		if (range <= min_range)
		{

			#if LANDING_DEBUG >= 2

			debug_log ("AI_MISC: EARLY OUT: found waypoint %d (type %d) range %f", current_waypoint, entity_sub_type_waypoint_names [get_local_entity_int_value (current_waypoint, INT_TYPE_ENTITY_SUB_TYPE)], range);

			#endif

			return current_waypoint;
		}

		if (range < best_range)
		{

			best_range = range;

			closest_waypoint = current_waypoint;

			#if LANDING_DEBUG

			debug_log ("AI_MISC: found waypoint %d (type %d) range %f", current_keysite, entity_sub_type_waypoint_names [get_local_entity_int_value (current_waypoint, INT_TYPE_ENTITY_SUB_TYPE)], range);

			#endif
		}

		current_waypoint = get_local_entity_child_succ (current_waypoint, LIST_TYPE_WAYPOINT);
	} 

	if ( closest_waypoint )
	{

		waypoint_pos = get_local_entity_vec3d_ptr (closest_waypoint, VEC3D_TYPE_POSITION);

		best_range = get_2d_range (waypoint_pos, pos);
	}

	if (actual_range)
	{

		*actual_range = best_range;
	}

	return closest_waypoint;
}
Beispiel #8
0
entity *get_closest_halfway_waypoint (entity *task, vec3d *pos, float min_range, float *actual_range)
{

	float
		best_range,
		range;

	vec3d
		*waypoint_pos1,
		*waypoint_pos2,
		mid_pos;

	entity
		*closest_waypoint = NULL,
		*waypoint1,
		*waypoint2;

	best_range = 99999999;

	waypoint1 = get_local_entity_first_child (task, LIST_TYPE_WAYPOINT);
	waypoint2 = get_local_entity_child_succ (waypoint1, LIST_TYPE_WAYPOINT);

	while (waypoint2)
	{

		waypoint_pos1 = get_local_entity_vec3d_ptr (waypoint1, VEC3D_TYPE_POSITION);
		waypoint_pos2 = get_local_entity_vec3d_ptr (waypoint2, VEC3D_TYPE_POSITION);

		mid_pos.x = waypoint_pos1->x + ( ( waypoint_pos2->x - waypoint_pos1->x ) / 2 );
		mid_pos.y = waypoint_pos1->y + ( ( waypoint_pos2->y - waypoint_pos1->y ) / 2 );
		mid_pos.z = waypoint_pos1->z + ( ( waypoint_pos2->z - waypoint_pos1->z ) / 2 );

		range = get_approx_2d_range (&mid_pos, pos);

		if (range < best_range)
		{

			best_range = range;
			closest_waypoint = waypoint1;
		}

		waypoint1 = waypoint2;
		waypoint2 = get_local_entity_child_succ (waypoint2, LIST_TYPE_WAYPOINT);
	}

	if ( closest_waypoint )
	{

		waypoint1 = closest_waypoint;
		waypoint2 = get_local_entity_child_succ (waypoint1, LIST_TYPE_WAYPOINT);

		waypoint_pos1 = get_local_entity_vec3d_ptr (waypoint1, VEC3D_TYPE_POSITION);
		waypoint_pos2 = get_local_entity_vec3d_ptr (waypoint2, VEC3D_TYPE_POSITION);

		mid_pos.x = waypoint_pos1->x + ( ( waypoint_pos2->x - waypoint_pos1->x ) / 2 );
		mid_pos.y = waypoint_pos1->y + ( ( waypoint_pos2->y - waypoint_pos1->y ) / 2 );
		mid_pos.z = waypoint_pos1->z + ( ( waypoint_pos2->z - waypoint_pos1->z ) / 2 );

		best_range = get_2d_range (&mid_pos, pos);
	}

	if (actual_range)
	{

		*actual_range = best_range;
	}

	return ( closest_waypoint );
}