Exemplo n.º 1
0
int group_task_specific_retaliation_checks (entity *group, entity *aggressor, int assisted)
{
	entity
		*task,
		*objective;

	task_roe_types
		roe;

	entity_sides
		side;

	vec3d
		*group_pos,
		*objective_pos,
		*aggressor_pos;

	int
		sx,
		sz;

	ASSERT (get_comms_model () == COMMS_MODEL_SERVER);

	ASSERT (group);

	ASSERT (aggressor);

	if (get_local_entity_int_value (group, INT_TYPE_AIRCRAFT_GROUP))
	{
		task = get_local_group_primary_task (group);

		if (!task)
		{
			return FALSE;
		}

		if (get_local_entity_int_value (aggressor, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI)
		{
			return TRUE;
		}

		roe = get_local_entity_int_value (task, INT_TYPE_RULES_OF_ENGAGEMENT);

		switch (roe)
		{
			case TASK_ROE_NONE:
			{
				//
				// FALSE if aggressor is within target area (stop RECON missions from destroying objectives)
				//

				if (get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_TASK_RECON)
				{
					objective = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT);

					if (objective)
					{
						objective_pos = get_local_entity_vec3d_ptr (objective, VEC3D_TYPE_POSITION);
	
						ASSERT (objective_pos);
	
						aggressor_pos = get_local_entity_vec3d_ptr (aggressor, VEC3D_TYPE_POSITION);
	
						ASSERT (aggressor_pos);
	
						if (get_sqr_2d_range (aggressor_pos, objective_pos) < ((2.0 * KILOMETRE) * (2.0 * KILOMETRE)))
						{
							ai_log ("(RETALIATE CHECK) ROE NONE - Failed (Aggressor at target area)");
	
							return FALSE;
						}
					}
				}

				//
				// Retaliate if no-one else coming to assist, AND (mission complete OR aggressor in friendly territory)
				//

				if (!assisted)
				{
					if (get_local_entity_int_value (task, INT_TYPE_TASK_COMPLETED) != TASK_INCOMPLETE)
					{
						ai_log ("(RETALIATE CHECK) ROE NONE - Task Complete");

						return TRUE;
					}

					side = get_local_entity_int_value (group, INT_TYPE_SIDE);

					group_pos = get_local_entity_vec3d_ptr (group, VEC3D_TYPE_POSITION);

					ASSERT (group_pos);

					get_x_sector (sx, group_pos->x);
					get_z_sector (sz, group_pos->z);

					if (get_local_sector_side_ratio (sx, sz, side) > 0.5)
					{
						ai_log ("(RETALIATE CHECK) ROE NONE - Friendly Territory");

						return TRUE;
					}
				}

				ai_log ("(RETALIATE CHECK) ROE NONE - Failed Checks");

				break;
			}
			case TASK_ROE_OBJECTIVE:
			{
				//
				// Retaliate if no-one else coming to assist, OR primary task completed
				//

				if (!assisted)
				{
					ai_log ("(RETALIATE CHECK) ROE OBJECTIVE - No Assistance");

					return TRUE;
				}

				if (get_local_entity_int_value (task, INT_TYPE_TASK_COMPLETED) != TASK_INCOMPLETE)
				{
					ai_log ("(RETALIATE CHECK) ROE OBJECTIVE - Task Complete");

					return TRUE;
				}

				ai_log ("(RETALIATE CHECK) ROE OBJECTIVE - Failed Checks");

				break;
			}
			case TASK_ROE_ALL:
			{
				//
				// Always retaliate
				//

				ai_log ("(RETALIATE CHECK) ROE ALL");

				return TRUE;
			}
		}

		return FALSE;
	}
	else
	{
		return TRUE;
	}
}
Exemplo n.º 2
0
unsigned int assign_engage_tasks_to_group (entity *group, unsigned int valid_members)
{
	entity
		*task,
		*guide,
		*target,
		*member,
		*single_member,
		*persuer,
		**guide_list;

	unsigned int
		member_number;

	int
		best_count,
		best_guide,
		loop,
		criteria,
		task_count,
		*assigned_count;

	float
		range,
		*priority;

	vec3d
		*member_pos,
		*target_pos;

	ASSERT (group);

	ASSERT (get_comms_model () == COMMS_MODEL_SERVER);

	if (!valid_members)
	{
		return valid_members;
	}	

	//
	// count up engage tasks
	//

	task_count = 0;

	guide = get_local_entity_first_child (group, LIST_TYPE_GUIDE_STACK);

	while (guide)
	{
		if (get_local_entity_int_value (guide, INT_TYPE_VALID_GUIDE_MEMBERS) == TASK_ASSIGN_NO_MEMBERS)
		{
			task = get_local_entity_parent (guide, LIST_TYPE_GUIDE);

			ASSERT (task);

			ASSERT (get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_TASK_ENGAGE);

			if (get_local_entity_int_value (task, INT_TYPE_TASK_TERMINATED) == TASK_TERMINATED_IN_PROGRESS)
			{
				task_count ++;
			}
		}

		guide = get_local_entity_child_succ (guide, LIST_TYPE_GUIDE_STACK);
	}

	#if DEBUG_MODULE

	debug_log ("ENGAGE: ==========================");
	
	debug_log ("ENGAGE: %d suitable tasks", task_count);

	#endif

	if (task_count == 0)
	{
		return valid_members;
	}

	//////////////////////////////////////////////////////////////////
	//
	// prioritize engage tasks
	//
	//////////////////////////////////////////////////////////////////

	//
	// get target priority
	//

	guide_list = (entity * *) malloc_fast_mem (sizeof (entity *) * task_count);
	priority = (float *) malloc_fast_mem (sizeof (float) * task_count);
	assigned_count = (int *) malloc_fast_mem (sizeof (int) * task_count);

	#if DEBUG_MODULE

	debug_log ("ENGAGE: ======RAW LIST======");

	#endif

	single_member = NULL;
	// check if we have a single member, if so assign that member to single_member
	for (member = get_local_entity_first_child (group, LIST_TYPE_MEMBER);
		 member;
		 member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER))
	{
		member_number = (1 << get_local_entity_int_value (member, INT_TYPE_GROUP_MEMBER_NUMBER));

		if (member_number & valid_members)
		{
			if (single_member)  // we already have a valid member, so there is more than one
			{
				single_member = NULL;
				break;
			}
			else
				single_member = member;
		}
	}

	loop = 0;
	guide = get_local_entity_first_child (group, LIST_TYPE_GUIDE_STACK);

	while (guide)
	{
		if (get_local_entity_int_value (guide, INT_TYPE_VALID_GUIDE_MEMBERS) == TASK_ASSIGN_NO_MEMBERS)
		{
			task = get_local_entity_parent (guide, LIST_TYPE_GUIDE);

			ASSERT (task);

			ASSERT (get_local_entity_int_value (task, INT_TYPE_ENTITY_SUB_TYPE) == ENTITY_SUB_TYPE_TASK_ENGAGE);

			if (get_local_entity_int_value (task, INT_TYPE_TASK_TERMINATED) == TASK_TERMINATED_IN_PROGRESS)
			{
				target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT);

				ASSERT (target);

				if (!target)
				{
					notify_local_entity (ENTITY_MESSAGE_TASK_TERMINATED, task, group, TASK_TERMINATED_ABORTED);

					free_mem (guide_list);
				
					free_mem (priority);
				
					free_mem (assigned_count);
				
					return valid_members;
				}
				
				guide_list [loop] = guide;

				if (get_local_entity_int_value (group, INT_TYPE_AIRCRAFT_GROUP))
				{
					priority [loop] = get_local_entity_float_value (target, FLOAT_TYPE_TARGET_PRIORITY_AIR_ATTACK);
				}
				else
				{
					priority [loop] = get_local_entity_float_value (target, FLOAT_TYPE_TARGET_PRIORITY_GROUND_ATTACK);
				}

				#if DEBUG_MODULE

				debug_log ("ENGAGE: (%d) Target : %s, Priority %f", loop, get_local_entity_string (target, STRING_TYPE_FULL_NAME), priority [loop]);

				#endif

				loop ++;
			}
		}

		guide = get_local_entity_child_succ (guide, LIST_TYPE_GUIDE_STACK);
	}

	ASSERT (loop == task_count);

	//
	// sort the tasks according to their priority
	//

	quicksort_entity_list (guide_list, task_count, priority);

	#if DEBUG_MODULE

	debug_log ("ENGAGE: ======SORTED======");

	for (loop = 0; loop < task_count; loop ++)
	{
		task = get_local_entity_parent (guide_list [loop], LIST_TYPE_GUIDE);

		target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT);

		debug_log ("ENGAGE: (%d) Target : %s (%d), Priority %f", loop, get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target), priority [loop]);
	}

	#endif

	//
	// consider other entities attacking the same targets
	//

	memset (assigned_count, 0, sizeof (int) * task_count);

	for (loop = 0; loop < task_count; loop ++)
	{
		task = get_local_entity_parent (guide_list [loop], LIST_TYPE_GUIDE);

		target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT);

		persuer = get_local_entity_first_child (target, LIST_TYPE_TARGET);

		while (persuer)
		{
			assigned_count [loop] ++;

			persuer = get_local_entity_child_succ (persuer, LIST_TYPE_TARGET);
		}
	}

	//////////////////////////////////////////////////////////////////
	//
	// assign new engage tasks
	//
	// for each member, run through the task list (most important first)
	// try to assign one member per task, but as tasks run out group members can "team-up"
	//
	//////////////////////////////////////////////////////////////////

	member = get_local_entity_first_child (group, LIST_TYPE_MEMBER);

	while ((member) && (valid_members))
	{
		//
		// Only assign AI entities to ENGAGE tasks
		//
		
		if (get_local_entity_int_value (member, INT_TYPE_PLAYER) == ENTITY_PLAYER_AI)
		{
			if (get_local_entity_int_value (member, INT_TYPE_ENGAGE_ENEMY))
			{
				member_number = (1 << get_local_entity_int_value (member, INT_TYPE_GROUP_MEMBER_NUMBER));

				if (member_number & valid_members)
				{
					member_pos = get_local_entity_vec3d_ptr (member, VEC3D_TYPE_POSITION);

					if (get_local_entity_int_value (member, INT_TYPE_IDENTIFY_AIRCRAFT))
					{
						criteria = BEST_WEAPON_CRITERIA_MINIMAL;
					}
					else
					{
						criteria = BEST_WEAPON_RANGE_CHECK | BEST_WEAPON_LOS_CHECK;
					}
		
					best_guide = -1;
			
					best_count = INT_MAX;
			
					for (loop = 0; loop < task_count; loop ++)
					{
						if (assigned_count [loop] < best_count)
						{
							guide = guide_list [loop];					
			
							task = get_local_entity_parent (guide, LIST_TYPE_GUIDE);
			
							target = get_local_entity_parent (task, LIST_TYPE_TASK_DEPENDENT);

							if (target == member)
							{
								//
								// Don't try to attack yourself !
								//
								
								continue;
							}

							//
							// Range Check
							//

							if (criteria & BEST_WEAPON_RANGE_CHECK)
							{
								// range handled by weapon selection
								range = 0.0;
							}
							else
							{
								target_pos = get_local_entity_vec3d_ptr (target, VEC3D_TYPE_POSITION);

								range = get_sqr_2d_range (target_pos, member_pos);
							}
							
							if (range < MAX_ENGAGE_RANGE)
							{
								//
								// Weapon Check
								//
				
								if (get_best_weapon_for_target (member, target, criteria) != ENTITY_SUB_TYPE_WEAPON_NO_WEAPON)
								{
									best_count = assigned_count [loop];
				
									best_guide = loop;
								}
							}
						}
					}
			
					if (best_guide != -1)
					{
						guide = guide_list [best_guide];
						
						task = get_local_entity_parent (guide, LIST_TYPE_GUIDE);
			
						if (assign_new_task_to_group_member (group, member, task, NULL))
						{
							valid_members &= (~member_number);
				
							assigned_count [best_guide] ++;
			
							#if DEBUG_MODULE
						
							debug_log ("ENGAGE: Assigning %s (%d) to target %s (%d)",
											get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member),
											get_local_entity_string (target, STRING_TYPE_FULL_NAME), get_local_entity_index (target));
		
							#endif
						}
					}
					else
					{
						#if DEBUG_MODULE
						
						debug_log ("ENGAGE: Couldn't assign %s (%d) to engage task",
										get_local_entity_string (member, STRING_TYPE_FULL_NAME), get_local_entity_index (member));
		
						#endif
					}
				}
			}
		}
		
		member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER);
	}

	free_mem (guide_list);

	free_mem (priority);

	free_mem (assigned_count);

	return valid_members;
}
Exemplo n.º 3
0
entity *regen_update (entity *en)
{

	regen_management_element
		*m1;

	entity_sub_types
		member_type,
		group_type;

	entity
		*wp,
		*task,
		*group,
		*member,
		*building,
		*force_en,
		*landing,
		*keysite;

	unsigned int
		member_number;

	int
		reserve_count;

	force
		*force_raw;

	regen
		*raw;

	regen_list_element
		*e1;

	raw = (regen *) get_local_entity_data (en);

	wp = get_local_entity_parent (en, LIST_TYPE_CURRENT_WAYPOINT);

	task = get_local_entity_parent (wp, LIST_TYPE_WAYPOINT);

	landing = get_local_entity_parent (task, LIST_TYPE_UNASSIGNED_TASK);
			
	keysite = get_local_entity_parent (landing, LIST_TYPE_LANDING_SITE);

	force_en = get_local_force_entity ((entity_sides) raw->side);

	force_raw = (force *) get_local_entity_data (force_en);

	group_type = NUM_ENTITY_SUB_TYPE_GROUPS;

	m1 = &regen_manager [raw->side][raw->sub_type];

	//
	// is there anything in the regen queues?
	//
	
	if (m1->count == 0)
	{
		return NULL;
	}

	//
	// Can regen operate
	//

	building = raw->member_root.first_child;

	if ((!get_local_entity_int_value (building, INT_TYPE_ALIVE)) || (get_local_entity_int_value (keysite, INT_TYPE_KEYSITE_USABLE_STATE) != KEYSITE_STATE_USABLE))
	{
		#if DEBUG_MODULE

		debug_log ("RG_UPDT: keysite %s too damaged to regen", get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME));

		#endif

		return NULL;
	}

	e1 = &regen_queue [raw->side][raw->sub_type][m1->front];

	ASSERT (e1->type != -1);
	ASSERT (e1->sub_type != -1);
	ASSERT (e1->group != -1);

	// is there a reserve of this type?
	if ((e1->type == ENTITY_TYPE_FIXED_WING) || (e1->type == ENTITY_TYPE_HELICOPTER))
	{
		reserve_count = force_raw->force_info_reserve_hardware[aircraft_database[e1->sub_type].force_info_catagory];
	}
	else
	{
		reserve_count = force_raw->force_info_reserve_hardware[vehicle_database[e1->sub_type].force_info_catagory];
	}

	if (reserve_count <= 0)
	{
		return NULL;
	}

	#if DEBUG_MODULE

	debug_log ("RG_UPDT: Trying to Regen %s Sub Type %d at %s - reserve count %d",
								get_entity_type_name (e1->type), e1->sub_type,
								get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME), reserve_count);

	#endif

	//
	// Don't regen if PLAYER landed there
	//

	group = get_local_entity_first_child (keysite, LIST_TYPE_KEYSITE_GROUP);

	while (group)
	{
		member = get_local_entity_first_child (group, LIST_TYPE_MEMBER);

		while (member)
		{

			if (get_local_entity_int_value (member, INT_TYPE_PLAYER) != ENTITY_PLAYER_AI)
			{

				if (get_local_entity_int_value (member, INT_TYPE_LANDED))
				{
					#if DEBUG_MODULE

					debug_log ("RG_UPDT: PLAYER landed at keysite %s, can't regen", get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME));

					#endif

					return NULL;
				}
			}

			member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER);
		}

		group = get_local_entity_child_succ (group, LIST_TYPE_KEYSITE_GROUP);
	}

	group_type = e1->group;
	
	member_type = e1->sub_type;

	////////////////////////////////////////////////////////////////////////////
	// Dont regen people or transport aircraft in apache havoc campaign as airport might not be correct (landing routes etc)
	////////////////////////////////////////////////////////////////////////////
	if (get_local_entity_int_value (get_session_entity (), INT_TYPE_CAMPAIGN_REQUIRES_APACHE_HAVOC))
	{

		switch (get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE))
		{

			case ENTITY_SUB_TYPE_REGEN_PEOPLE:
			{

				#if DEBUG_MODULE

				debug_log ("RG_UPDT: Stopping Regening People - wrong warzone");

				#endif

				return NULL;
			}

			case ENTITY_SUB_TYPE_REGEN_FIXED_WING:
			{

				if (group_database [group_type].default_landing_type == ENTITY_SUB_TYPE_LANDING_FIXED_WING_TRANSPORT)
				{

					#if DEBUG_MODULE

					debug_log ("RG_UPDT: Stopping Regening Transport aircraft - wrong warzone");

					#endif

					return NULL;
				}
			}
		}
	}
	////////////////////////////////////////////////////////////////////////////
	// Dont regen people or transport aircraft in apache havoc campaign as airport might not be correct (landing routes etc)
	////////////////////////////////////////////////////////////////////////////

	if (group_type != NUM_ENTITY_SUB_TYPE_GROUPS)
	{

		int
			route_node;

		entity
			*building,
			*member,
			*guide,
			*group = NULL;

		group = create_landing_faction_members (keysite, member_type, group_type, 1, wp, &raw->position);

		if (group)
		{

			//
			// Assign closest route_node (only needed for routed vehicles)
			//

			if (get_local_entity_int_value (group, INT_TYPE_FRONTLINE))
			{
	
				route_node = get_closest_side_road_node ((entity_sides) get_local_entity_int_value (group, INT_TYPE_SIDE), &raw->position, 5 * KILOMETRE);
	
				set_client_server_entity_int_value (group, INT_TYPE_ROUTE_NODE, route_node);
			}

			//
			//
			//
			
			member = get_local_entity_first_child (group, LIST_TYPE_MEMBER);

			//
			// close members doors
			//

			close_client_server_entity_cargo_doors (member);

			close_client_server_entity_loading_doors (member);

			//
			// open building doors
			//

			building = get_local_entity_first_child (en, LIST_TYPE_MEMBER);

			open_client_server_entity_loading_doors (building);

			set_local_entity_float_value (building, FLOAT_TYPE_LOADING_DOOR_TIMER, 30.0);

			//
			// create guide entity for task (TEST)
			//

			// Debug for Transport aircraft.
			// Locate nearest Transport landing wp and insert into it
			if (group_database [group_type].default_landing_type == ENTITY_SUB_TYPE_LANDING_FIXED_WING_TRANSPORT)
			{

				float
					range,
					best_range;

				entity
					*transport_wp,
					*transport_task,
					*transport_landing;

				best_range = 999999999.0;

				transport_landing = get_local_entity_landing_entity (keysite, ENTITY_SUB_TYPE_LANDING_FIXED_WING_TRANSPORT);

				if (transport_landing)
				{
	
					transport_task = get_local_landing_entity_task (transport_landing, ENTITY_SUB_TYPE_TASK_LANDING);

					ASSERT (transport_task);
	
					transport_wp = get_local_entity_first_child (transport_task, LIST_TYPE_WAYPOINT);

					ASSERT (transport_wp);
	
					while (transport_wp)
					{
	
						range = get_sqr_2d_range (get_local_entity_vec3d_ptr (transport_wp, VEC3D_TYPE_POSITION), get_local_entity_vec3d_ptr (building, VEC3D_TYPE_POSITION));
	
						if (range < best_range)
						{
	
							wp = transport_wp;
	
							task = transport_task;
	
							best_range = range;
						}
	
						transport_wp = get_local_entity_child_succ (transport_wp, LIST_TYPE_WAYPOINT);
					}
				}
			}
			// Debug for Transport aircraft.

			member_number = get_local_entity_int_value (member, INT_TYPE_GROUP_MEMBER_NUMBER);

			guide = create_client_server_guide_entity (task, wp, (1 << member_number));

			attach_group_to_guide_entity (group, guide);

			attach_group_member_to_guide_entity (member, guide);

			//#if DEBUG_MODULE
			{

				entity
					*keysite;

				keysite = get_local_entity_parent (landing, LIST_TYPE_LANDING_SITE);

				member = get_local_entity_first_child (group, LIST_TYPE_MEMBER);

				debug_log ("RG_UPDT: %s creating %s (%d) at keysite %s free landing sites %d, reserved %d, lock %d, available lock: %d",
						entity_side_names [get_local_entity_int_value (keysite, INT_TYPE_SIDE)],
						get_local_entity_type_name (member),
						get_local_entity_index (member),
						get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME), 
						get_local_entity_int_value (landing, INT_TYPE_FREE_LANDING_SITES),
						get_local_entity_int_value (landing, INT_TYPE_RESERVED_LANDING_SITES),
						get_local_entity_int_value (landing, INT_TYPE_LANDING_LOCK),
						check_available_landing_route_lock (landing)
						);

				if ((e1->type == ENTITY_TYPE_FIXED_WING) || (e1->type == ENTITY_TYPE_HELICOPTER))
				{
					debug_log("%s reserves left: %d",
							force_info_catagory_names[aircraft_database[e1->sub_type].force_info_catagory],
							force_raw->force_info_reserve_hardware[aircraft_database[e1->sub_type].force_info_catagory]
							);
				}
				else
				{
					debug_log("%s reserves left: %d",
							force_info_catagory_names[vehicle_database[e1->sub_type].force_info_catagory],
							force_raw->force_info_reserve_hardware[vehicle_database[e1->sub_type].force_info_catagory]
							);
				}

			}
			//#endif

			#if DEBUG_MODULE
			switch (e1->type)
			{
				case ENTITY_TYPE_FIXED_WING:
				case ENTITY_TYPE_HELICOPTER:
				{
					ASSERT (regen_ac_debug[e1->sub_type] > 0);

					break;
				}
				
				case ENTITY_TYPE_ROUTED_VEHICLE:
				case ENTITY_TYPE_SHIP_VEHICLE:
				case ENTITY_TYPE_PERSON:
				{
					ASSERT (regen_vh_debug[e1->sub_type] > 0);

					break;
				}
				
				default:
				{
					debug_fatal ("RG_UPDT: Unknown entity type for debug");
				}
				
			}
			#endif

			// update markers
			regen_queue_use ((entity_sides) raw->side, (raw->sub_type));

			return member;
		}
	}
	else
	{
		#if DEBUG_MODULE >= 2

		debug_log ("RG_UPDT: not creating anything at keysite %s free landing sites %d, reserved %d, lock %d",
						get_local_entity_string (keysite, STRING_TYPE_KEYSITE_NAME), 
						get_local_entity_int_value (landing, INT_TYPE_FREE_LANDING_SITES),
						get_local_entity_int_value (landing, INT_TYPE_RESERVED_LANDING_SITES),
						check_available_landing_route_lock (landing));

		#endif
	}

	return NULL;
}