Beispiel #1
0
//-------- Begin of function Nation::ai_sea_travel -------//
//
// action_x_loc, action_y_loc - location of the destination
//
// group_unit_array - array of units that will do the sea travel
// instance_count - no. of units in the array
//
// action_para  - the action of units after they have arrived the region,
//					   it is one of the following:
//
// SEA_ACTION_SETTLE		 	  - settle into a town
//	SEA_ACTION_BUILD_CAMP 	  - build and assign to a firm
//	SEA_ACTION_ASSIGN_TO_FIRM - assign to a firm
//	SEA_ACTION_MOVE			  - just move to the destination
//								 	    (this include moving to the location of a battle field.)
//
//---------------------------------------------//
//
// Procedures:
// * 1. Locate a ship, build one if cannot locate any.
// * 2. Assign the units to the ship.
//   3. Move the ship to the destination region.
//   4. Units disembark on the coast.
//   5. Units move to the destination.
//
// This function deal with the 1st and 2nd procedures,
// when they are finished, action ACTION_AI_SEA_TRAVEL2
// will be added.
//
//---------------------------------------------//
//
int Nation::ai_sea_travel(ActionNode* actionNode)
{
	err_when( actionNode->instance_count < 1 ||
				 actionNode->instance_count > ActionNode::MAX_ACTION_GROUP_UNIT );

	Unit* unitPtr = unit_array[actionNode->group_unit_array[0]];

	err_when( unitPtr->nation_recno != nation_recno );
	err_when( !unitPtr->is_visible() );

	//---- figure out the sea region id which the ship should appear ----//

	int unitRegionId = world.get_region_id(unitPtr->next_x_loc(), unitPtr->next_y_loc());
	int destRegionId = world.get_region_id(actionNode->action_x_loc, actionNode->action_y_loc);

	int seaRegionId = region_array.get_sea_path_region_id(unitRegionId, destRegionId);

	//------- 1. try to locate a ship --------//

	int shipUnitRecno = ai_find_transport_ship(seaRegionId, unitPtr->next_x_loc(), unitPtr->next_y_loc());

	if( !shipUnitRecno )
		return -1;					// must return -1 instead of 0 as the action must be executed immediately otherwise the units will be assigned with other action and the unit list may no longer be valid

	//---- if this ship is in the harbor, sail it out ----//

	UnitMarine* unitMarine = (UnitMarine*) unit_array[shipUnitRecno];

	if( unitMarine->unit_mode == UNIT_MODE_IN_HARBOR )
	{
		FirmHarbor*	firmHarbor = (FirmHarbor*) firm_array[unitMarine->unit_mode_para];

		firmHarbor->sail_ship(unitMarine->sprite_recno, COMMAND_AI);
	}

	if( !unitMarine->is_visible() )		// no space in the sea for placing the ship 
		return -1;

	//------ 2. Assign the units to the ship -------//

	unitMarine->ai_action_id = actionNode->action_id;

	err_when( unit_res[unitMarine->unit_id]->unit_class != UNIT_CLASS_SHIP );

	// ##### patch begin Gilbert 5/8 #######//
	unit_array.assign_to_ship(unitMarine->next_x_loc(), unitMarine->next_y_loc(), 0, actionNode->group_unit_array, actionNode->instance_count, COMMAND_AI, unitMarine->sprite_recno );
	// ##### patch end Gilbert 5/8 #######//

	for( int i=0 ; i<actionNode->instance_count ; i++ )
		unit_array[ actionNode->group_unit_array[i] ]->ai_action_id = actionNode->action_id;

	actionNode->instance_count++;		// +1 for the ship

	actionNode->processing_instance_count = actionNode->instance_count-1;		// -1 because when we return 1, it will be increased by 1 automatically
	actionNode->action_para2 = 0;		// reset it, it is set in Nation::action_finished()

	return 1;
}
Beispiel #2
0
//--------- Begin of function Unit::process_assign_to_ship ---------//
// process unit action of assigning units to ship
//
void Unit::process_assign_to_ship()
{
	err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
	
	//---------------------------------------------------------------------------//
	// clear unit's action if situation is changed
	//---------------------------------------------------------------------------//
	UnitMarine *shipPtr;
	if(unit_array.is_deleted(action_para2))
	{
		stop2();
		return; // stop the unit as the ship is deleted
	}
	else
	{
		shipPtr = (UnitMarine*) unit_array[action_para2];
		if(shipPtr->nation_recno != nation_recno)
		{
			stop2();
			return; // stop the unit as the ship's nation_recno != the unit's nation_recno
		}
	}

	if(shipPtr->action_mode2!=ACTION_SHIP_TO_BEACH)
	{
		stop2(); // the ship has changed its action
		return;
	}

	int curXLoc = next_x_loc();
	int curYLoc = next_y_loc();
	int shipXLoc = shipPtr->next_x_loc();
	int shipYLoc = shipPtr->next_y_loc();

	if(shipPtr->cur_x==shipPtr->next_x && shipPtr->cur_y==shipPtr->next_y &&
		abs(shipXLoc-curXLoc)<=1 && abs(shipYLoc-curYLoc)<=1)
	{
		//----------- assign the unit now -----------//
		if(abs(cur_x-next_x)<sprite_info->speed && abs(cur_y-next_y)<sprite_info->speed)
		{
			if(ai_action_id)
				nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);

			stop2();
			set_dir(curXLoc, curYLoc, shipXLoc, shipYLoc);
			shipPtr->load_unit(sprite_recno);
			return;
		}
	}
	else if(cur_action==SPRITE_IDLE)
		set_dir(curXLoc, curYLoc, shipPtr->move_to_x_loc, shipPtr->move_to_y_loc);

	//---------------------------------------------------------------------------//
	// update location to embark
	//---------------------------------------------------------------------------//
	int shipActionXLoc = shipPtr->action_x_loc2;
	int shipActionYLoc = shipPtr->action_y_loc2;
	if(abs(shipActionXLoc-action_x_loc2)>1 || abs(shipActionYLoc-action_y_loc2)>1)
	{
		if(shipActionXLoc!=action_x_loc2 || shipActionYLoc!=action_y_loc2)
		{
			Location *unitLocPtr = world.get_loc(curXLoc, curYLoc);
			Location *shipActionLocPtr = world.get_loc(shipActionXLoc, shipActionYLoc);
			if(unitLocPtr->region_id != shipActionLocPtr->region_id)
			{
				stop2();
				return;
			}

			assign_to_ship(shipActionXLoc, shipActionYLoc, action_para2);
			return;
		}
	}
}
Beispiel #3
0
//-------- Begin of function Nation::ai_find_transport_ship -------//
//
// Locate a ship for transporting units.
//
// <int> seaRegionId			 - region id. of the sea which the ship should appear in.
// <int> unitXLoc, unitYLoc - the location of the units to be picked up,
//									   try to select a harbor close to this location.
// [int] findBest           - whether need to find the best ship or just return
//									   one if there is one found. (default: 1)
//
// return: <int> the recno of the ship located.
//
int Nation::ai_find_transport_ship(int seaRegionId, int unitXLoc, int unitYLoc, int findBest)
{
	//------- locate a suitable ship --------//

	UnitMarine* unitMarine;
	int			curRating, bestRating=0, bestUnitRecno=0;

	for( int i=0 ; i<ai_ship_count ; i++ )
	{
		unitMarine = (UnitMarine*) unit_array[ ai_ship_array[i] ];

		err_when( unit_res[unitMarine->unit_id]->unit_class != UNIT_CLASS_SHIP );

		if( unitMarine->unit_count > 0 ||										// if there are already units in the ship
			 unit_res[unitMarine->unit_id]->carry_unit_capacity==0 )		// if the ship does not carry units
		{
			continue;
		}

		//------- if this ship is in the harbor ---------//

		if( unitMarine->unit_mode == UNIT_MODE_IN_HARBOR )
		{
			FirmHarbor* firmHarbor = (FirmHarbor*) firm_array[unitMarine->unit_mode_para];

			err_when( firmHarbor->firm_id != FIRM_HARBOR );

			if( firmHarbor->sea_region_id != seaRegionId )
				continue;
		}

		//--------- if this ship is on the sea ----------//

		else
		{
			if( !unitMarine->is_ai_all_stop() )
				continue;

			if( unitMarine->region_id() != seaRegionId )
				continue;

			err_when( !unitMarine->is_visible() );

			if( !unitMarine->is_visible() )
				continue;
		}

		//--------- check if the sea region is matched ---------//

		if( !findBest )		// return immediately when a suitable one is found
			return unitMarine->sprite_recno;

		curRating = world.distance_rating( unitXLoc, unitYLoc,
						unitMarine->next_x_loc(), unitMarine->next_y_loc() );

		curRating += (int)unitMarine->hit_points/10				// damage
						 + (int)unitMarine->max_hit_points/10;	// ship class

		if( curRating > bestRating )
		{
			bestRating 	  = curRating;
			bestUnitRecno = unitMarine->sprite_recno;
		}
	}

	return bestUnitRecno;
}