Example #1
0
entity *add_group_to_division (entity *group, entity *specified_division)
{
	entity_sides
		side;

	int
		count,
		max_count,
		group_type,
		keysite_type,
		division_type,
		main_division_type;

	entity
		*en,
		*force,
		*keysite,
		*division;

	vec3d
		*group_pos;
		
	ASSERT (group);

	ASSERT (get_comms_model () == COMMS_MODEL_SERVER);

	ASSERT (!get_local_entity_parent (group, LIST_TYPE_DIVISION));

	group_type = get_local_entity_int_value (group, INT_TYPE_ENTITY_SUB_TYPE);
	
	group_pos = get_local_entity_vec3d_ptr (group, VEC3D_TYPE_POSITION);
	
	if (specified_division)
	{
		division = specified_division;
	}
	else
	{
		side = (entity_sides) get_local_entity_int_value (group, INT_TYPE_SIDE);
	
		force = get_local_force_entity (side);
	
		ASSERT (force);
	
		division_type = group_database [group_type].default_group_division;
	
		ASSERT (entity_sub_type_division_valid (division_type));
	
		main_division_type = division_database [division_type].default_group_division;
	
		ASSERT (entity_sub_type_division_valid (main_division_type));
	
		//
		// Find the keysite the company should be attached to
		//

		keysite = NULL;
	
		if (get_local_entity_int_value (group, INT_TYPE_GROUP_LIST_TYPE) == LIST_TYPE_KEYSITE_GROUP)
		{
			keysite = get_local_entity_parent (group, LIST_TYPE_KEYSITE_GROUP);

			if (!keysite)
			{
				keysite = get_closest_keysite (NUM_ENTITY_SUB_TYPE_KEYSITES, side, group_pos, 1.0 * KILOMETRE, NULL, NULL);
			}
	
			ASSERT (keysite);
	
			keysite_type = get_local_entity_int_value (keysite, INT_TYPE_ENTITY_SUB_TYPE);
	
			if ((keysite_type == ENTITY_SUB_TYPE_KEYSITE_AIRBASE) || (keysite_type == ENTITY_SUB_TYPE_KEYSITE_ANCHORAGE))
			{
				//
				// Use keysite landed at
				//
			}
			else
			{
				//
				// Find nearest keysite (below)
				//

				keysite = NULL;
			}
		}
		else
		{
			if (group_database [group_type].movement_type == MOVEMENT_TYPE_SEA)
			{
				//
				// Find nearest carrier
				//
			
				keysite = get_closest_keysite (ENTITY_SUB_TYPE_KEYSITE_ANCHORAGE, side, group_pos, 0.0, NULL, NULL);
			}
		}

		if (!keysite)
		{
			//
			// Find nearest airbase
			//
			
			keysite = get_closest_keysite (ENTITY_SUB_TYPE_KEYSITE_AIRBASE, side, group_pos, 0.0, NULL, NULL);

			if (!keysite)
			{
				//
				// Find nearest military base
				//
				
				keysite = get_closest_keysite (ENTITY_SUB_TYPE_KEYSITE_MILITARY_BASE, side, group_pos, 0.0, NULL, NULL);

				if (!keysite)
				{
					//
					// Find nearest FARP  
					//
				
					keysite = get_closest_keysite (ENTITY_SUB_TYPE_KEYSITE_FARP, side, group_pos, 0.0, NULL, NULL);
				}
			}
		}
	
		ASSERT (keysite);
	
		//
		// Check all companies at this keysite to see if they have vacancies....
		//
	
		max_count = group_database [group_type].maximum_groups_per_division;
	
		division = get_local_entity_first_child (keysite, LIST_TYPE_DIVISION_HEADQUARTERS);
	
		while (division)
		{
			if (get_local_entity_int_value (division, INT_TYPE_ENTITY_SUB_TYPE) == division_type)
			{
				if (max_count == 0)
				{
					break;
				}
	
				count = 0;
	
				en = get_local_entity_first_child (division, LIST_TYPE_DIVISION);
	
				while (en)
				{
					ASSERT (get_local_entity_type (en) == ENTITY_TYPE_GROUP);
	
					count ++;
	
					en = get_local_entity_child_succ (en, LIST_TYPE_DIVISION);
				}
	
				if (count < max_count)
				{
					break;
				}
			}
	
			division = get_local_entity_child_succ (division, LIST_TYPE_DIVISION_HEADQUARTERS);
		}
	
		if (division)
		{
			//
			// found an existing division with space available
			//
		}
		else
		{
			//
			// create a new division
			//
	
			entity
				*main_division;
	
			max_count = division_database [division_type].maximum_groups_per_division;
	
			main_division = get_local_entity_first_child (force, LIST_TYPE_DIVISION);
	
			while (main_division)
			{
				if (get_local_entity_int_value (main_division, INT_TYPE_ENTITY_SUB_TYPE) == main_division_type)
				{
					//
					// check division for vacancies
					//
	
					if (max_count == 0)
					{
						break;
					}
	
					count = 0;
	
					en = get_local_entity_first_child (main_division, LIST_TYPE_DIVISION);
	
					while (en)
					{
						ASSERT (get_local_entity_type (en) == ENTITY_TYPE_DIVISION);
	
						if (get_local_entity_int_value (en, INT_TYPE_ENTITY_SUB_TYPE) == division_type)
						{
							count ++;
						}
						
						en = get_local_entity_child_succ (en, LIST_TYPE_DIVISION);
					}
	
					if (count < max_count)
					{
						break;
					}
				}
	
				main_division = get_local_entity_child_succ (main_division, LIST_TYPE_DIVISION);
			}
	
			if (main_division)
			{
				//
				// found an existing division with space available
				//
			}
			else
			{
				//
				// create a new division
				//
	
				main_division = create_new_division (main_division_type, side, force, NULL, FALSE);
			}
	
			ASSERT (main_division);
	
			division = create_new_division (division_type, side, main_division, keysite, FALSE);
		}
	}

	ASSERT (division);

	set_client_server_entity_parent (group, LIST_TYPE_DIVISION, division);

	return division;
}
Example #2
0
int reassign_group_members_to_valid_tasks (entity *group, entity *last_task, unsigned int members_to_reassign, int engage_enemy)
{
	entity
		*guide,
		*member,
		*new_task;

	unsigned int
		member_number,
		valid_members;

	ASSERT (members_to_reassign != 0);

	//
	// first see if any engage tasks can be done
	//

	if (engage_enemy)
	{
		members_to_reassign = assign_engage_tasks_to_group (group, members_to_reassign);
	}

	if (!members_to_reassign)
	{
		//
		// all members have successfully been allocated engage tasks - so no need to worry about rest of the task stack
		//
		
		return TRUE;
	}

	//
	// take each member in the group that requires a new task
	//

	member = get_local_entity_first_child (group, LIST_TYPE_MEMBER);

	while (member)
	{
		member_number = (1 << get_local_entity_int_value (member, INT_TYPE_GROUP_MEMBER_NUMBER));

		if (members_to_reassign & member_number)
		{
			//
			// If the member gets here, then it can't be doing an engage task, hence it shouldn't have a target... (unless its a player)
			//

			if (get_local_entity_int_value (member, INT_TYPE_PLAYER) == ENTITY_PLAYER_AI)
			{
				if (get_local_entity_parent (member, LIST_TYPE_TARGET))
				{
					set_client_server_entity_parent (member, LIST_TYPE_TARGET, NULL);
				}
			}

			//
			// Look at each task on the stack
			//

			new_task = NULL;
	
			guide = get_local_entity_first_child (group, LIST_TYPE_GUIDE_STACK);

			while (guide)
			{
				//
				// is task meant for this member ?
				//

				valid_members = get_local_entity_int_value (guide, INT_TYPE_VALID_GUIDE_MEMBERS);

				if (valid_members & member_number)
				{
					new_task = get_local_entity_parent (guide, LIST_TYPE_GUIDE);

					if (get_local_entity_int_value (new_task, INT_TYPE_TASK_TERMINATED) == TASK_TERMINATED_IN_PROGRESS)
					{
						assign_new_task_to_group_member (group, member, new_task, guide);

						//
						// clear member flag, and skip to next group member
						//
							
						members_to_reassign &= (~member_number);
							
						break;
					}
				}
			
				new_task = NULL;

				guide = get_local_entity_child_succ (guide, LIST_TYPE_GUIDE_STACK);
			}
		}
		
		member = get_local_entity_child_succ (member, LIST_TYPE_MEMBER);
	}

	return TRUE;
}
Example #3
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;
}
Example #4
0
int assign_primary_task_to_group (entity *group_en, entity *task_en)
{
	entity_sub_types
		task_type,
		group_type;

	entity
		*force,
		*keysite;

	int
		side,
		formation,
		air_threat,
		enemy_sectors;

	unsigned int
		threat;

	ASSERT (get_comms_model () == COMMS_MODEL_SERVER);
		
	task_type = get_local_entity_int_value (task_en, INT_TYPE_ENTITY_SUB_TYPE);

	ASSERT (task_database [task_type].primary_task);

	group_type = get_local_entity_int_value (group_en, INT_TYPE_ENTITY_SUB_TYPE);

	ASSERT (!get_local_group_primary_task (group_en));

	if (assign_task_to_group (group_en, task_en, TASK_ASSIGN_ALL_MEMBERS))
	{
		//
		// set default group formation
		//

		formation = get_local_entity_int_value (group_en, INT_TYPE_GROUP_DEFAULT_FORMATION);

		if (formation != get_local_entity_int_value (group_en, INT_TYPE_GROUP_FORMATION))
		{
			set_client_server_entity_int_value (group_en, INT_TYPE_GROUP_FORMATION, formation);
		}

		//
		// Link to new keysite
		// 

		if (get_local_entity_int_value (group_en, INT_TYPE_GROUP_LIST_TYPE) == LIST_TYPE_KEYSITE_GROUP)
		{
			keysite = ( entity * ) get_local_entity_ptr_value (task_en, PTR_TYPE_RETURN_KEYSITE);

			if (keysite)
			{
				set_client_server_entity_parent (group_en, LIST_TYPE_KEYSITE_GROUP, keysite);
			}	
		}

		//
		// Notify Force
		//

		side = get_local_entity_int_value (group_en, INT_TYPE_SIDE);

		force = get_local_force_entity ( ( entity_sides ) side );

		ASSERT (force);

		notify_local_entity (ENTITY_MESSAGE_TASK_ASSIGNED, force, task_en);

		//
		// Assess for Escort task
		//

		if (task_database [task_type].escort_required_threshold != ESCORT_NEVER)
		{
			threat = assess_task_difficulty (task_en, &air_threat, &enemy_sectors);

			#if DEBUG_ESCORT_TASK_CREATION

			debug_filtered_log ("(ASSIGN) Side %s: Assigned %s to %s, objective %s",
											entity_side_short_names [side],
											get_local_entity_string (group_en, STRING_TYPE_FULL_NAME),
											get_local_entity_string (task_en, STRING_TYPE_FULL_NAME),
											get_task_objective_string (task_en)
									);

			debug_filtered_log ("Threat: %d (air_threat: %d, enemy_sectors: %d) - Threshold %d",
											threat, air_threat, enemy_sectors,
											task_database [task_type].escort_required_threshold);

			#endif

			if (threat >= task_database [task_type].escort_required_threshold)
			{
				create_escort_task (group_en, (threat >= ESCORT_CRITICAL), task_database [ENTITY_SUB_TYPE_TASK_ESCORT].task_priority, NULL, NULL);

				ai_log ("(ASSIGN) Created Escort Task for %s :- Threat %d / Threshold %d",
											get_local_entity_string (task_en, STRING_TYPE_FULL_NAME),
											threat,
											task_database [task_type].escort_required_threshold
											);
			}
		}

		//
		// Store Start Time
		//

		set_client_server_entity_float_value (task_en, FLOAT_TYPE_START_TIME, get_local_entity_float_value (get_session_entity (), FLOAT_TYPE_ELAPSED_TIME));

		//
		// Clear Expire Timer (now also used for destroying completed tasks)
		//

		set_local_entity_float_value (task_en, FLOAT_TYPE_EXPIRE_TIMER, 0.0);

		ai_log ("(ASSIGN) Side %s: Assigned %s (%d) to %s (%d) - Priority %f",
					entity_side_short_names [side],
					get_local_entity_string (group_en, STRING_TYPE_FULL_NAME),
					get_local_entity_safe_index (group_en),
					get_local_entity_string (task_en, STRING_TYPE_FULL_NAME),
					get_local_entity_safe_index (task_en),
					get_local_entity_float_value (task_en, FLOAT_TYPE_TASK_PRIORITY));

		return TRUE;
	}

	return FALSE;
}