Esempio n. 1
0
void UnitGroup::exe_assign(int destXLoc, int destYLoc, int targetMobileType, int actionNationRecno)
{
	//---------------------------------------//
	Unit* unitPtr;
	int locX, locY;

	int right = 0;
	int left = 0;
	int midX = 0;
	int top = 0;
	int bottom = 0;
	int midY = 0;

	if(size() == 1)
	{
		unitPtr = get_unit(1);
		unitPtr->set_no_longer_in_formation();
		unitPtr->assign(destXLoc, destYLoc, actionNationRecno);
		return;
	}

	Location* locPtr;

	locPtr = world.get_loc(destXLoc, destYLoc);
	int baseObjRecno = locPtr->base_obj_recno(targetMobileType); 
	// ###### begin Gilbert 6/5 #######//
	if( !baseObjRecno )
		return;
	// ###### end Gilbert 6/5 #######//
	BaseObj* thePlace = base_obj_array[baseObjRecno];
	int destWidth = thePlace->obj_loc_width();
	int destHeight = thePlace->obj_loc_height();

	for(int i = 1; i<=size(); i++)
	{
		unitPtr = get_unit(i);
		unitPtr->set_no_longer_in_formation();
		locX = unitPtr->next_x_loc();
		locY = unitPtr->next_y_loc();

		if(locX < destXLoc) //left
			left++;
		else if(locX > destXLoc+destWidth-1) //right
			right++;
		else
			midX++;
		if(locY < destYLoc) //top
			top++;
		else if(locY > destYLoc+destHeight-1) //bottom
			bottom++;
		else
			midY++;
	}
	if(!left && !midX) //all at right side
	{
		run_action( destXLoc, destYLoc, UNIT_ASSIGN, baseObjRecno );
		return;
	}
	if(!right && !midX) //all at left side
	{
		run_action( destXLoc, destYLoc, UNIT_ASSIGN, baseObjRecno );
		return;
	}
	if(!top && !midY) //all at bottom side
	{
		run_action( destXLoc, destYLoc, UNIT_ASSIGN, baseObjRecno);
		return;
	}
	if(!bottom && !midY) //all at top side
	{
		run_action(destXLoc, destYLoc, UNIT_ASSIGN, baseObjRecno);
		return;
	}

	for(i=1; i<=size(); i++)
	{
		unitPtr = get_unit(i);
		unitPtr->assign(destXLoc, destYLoc, actionNationRecno);
	}
}
Esempio n. 2
0
void UnitGroup::exe_attack(int targetObjRecno)
{
	BaseObj *targetObj = base_obj_array[targetObjRecno];

	int targetWidth = targetObj->obj_loc_width();
	int targetHeight = targetObj->obj_loc_height();
	int targetLocX = targetObj->obj_loc_x1();
	int targetLocY = targetObj->obj_loc_y1();
	/*
	int testLocX, testLocY;
	int index, unitIndex;
	int maxWidth=0, maxHeight=0;
	Unit* unitPtr;
	int w, h;
	int rangeAttack=0, closeAttack=0;
	int minAttackRange = 0;
	int distance;
	Unit** arrayForRangeAttack=NULL, **arrayForCloseAttack=NULL;
	int numberAttacking = 0;
	*/

	//--looking for the maximum range, size of the units ---//
	//--and counting how many units will do range attack and close attack respectively---//
	/*
	for(int i=1; i<=size(); i++)
	{
		unitPtr = get_unit(i);
		if(!unitPtr->can_attack())
			continue;

		//---------------------------------------------//

		if(unitPtr->cur_action == SPRITE_ATTACK && unitPtr->cur_order.para == targetObjRecno)
		{
			numberAttacking++;
			continue;
		}
		// ##### begin Gilbert 4/11 ######//
		// distance = unitPtr->cal_distance(targetLocX, targetLocY, targetWidth, targetHeight);
		distance = unitPtr->area_distance(targetObj);
		// ##### end Gilbert 4/11 ######//
		unitPtr->choose_best_attack_mode(distance, targetObj->obj_mobile_type());
		if(unitPtr->obj_loc_width() > maxWidth)
			maxWidth = unitPtr->obj_loc_width();
		if(unitPtr->obj_loc_height() > maxHeight)
			maxHeight = unitPtr->obj_loc_height();
		if((unitPtr->attack_range() < minAttackRange) && (unitPtr->attack_range()>1))
			minAttackRange = unitPtr->attack_range();
		if(unitPtr->attack_range() > 1)
			rangeAttack++;
		else
			closeAttack++;
	}
	//---------------------------------------------------------//
//	err_when(!rangeAttack && !closeAttack);
	if(!rangeAttack && !closeAttack)
		return;

	if(rangeAttack)
		arrayForRangeAttack = (Unit**) mem_add(sizeof(Unit*)*rangeAttack);
	if(closeAttack)
		arrayForCloseAttack = (Unit**) mem_add(sizeof(Unit*)*closeAttack);

	int iRa = 0, iCa = 0;
	//---- separate the units into two arrays by means of their attacking mode ---//
	for(i=1; i<=size(); i++)
	{
		unitPtr = get_unit(i);
		if(!unitPtr->can_attack())
			continue;

		if(unitPtr->cur_action == SPRITE_ATTACK && unitPtr->cur_order.para == targetObjRecno)
			continue;

		if(unitPtr->attack_range()>1)
			arrayForRangeAttack[iRa++] = unitPtr;
		else
			arrayForCloseAttack[iCa++] = unitPtr;
	}

	err_when(!maxWidth);
	err_when(!maxHeight);

	//----- assign a good location for the units to undergo range attack -----//
	if(rangeAttack)
	{
		int xLoc1 = max(targetLocX-minAttackRange, 0);
		int yLoc1 = max(targetLocY-minAttackRange, 0);
		int xLoc2 = min(targetLocX+targetWidth-1+minAttackRange, MAX_WORLD_X_LOC-1);
		int yLoc2 = min(targetLocY+targetHeight-1+minAttackRange, MAX_WORLD_Y_LOC-1);
		int checkXLoc, checkYLoc;
		unitIndex = 0;
		unitPtr = arrayForRangeAttack[unitIndex];

		//-------- checking for surrounding location ----------//
		for(checkXLoc=xLoc1; checkXLoc<=xLoc2; checkXLoc++)
		{
			if(unitPtr->can_move(checkXLoc, yLoc1))
			{
				unitPtr->attack_loc_offset_x = checkXLoc-targetLocX;
				unitPtr->attack_loc_offset_y = yLoc1-targetLocY;
				if(unitPtr->obj_loc_width()>1)
					checkXLoc += (unitPtr->obj_loc_width()-1);
				if(unitIndex<rangeAttack-1)
					unitPtr = arrayForRangeAttack[++unitIndex];
				else
					break;
			}
		}

		if(unitIndex < rangeAttack)
		{
			for(checkYLoc=yLoc1+1; checkYLoc<yLoc2; checkYLoc++)
			{
				if(unitPtr->can_move(xLoc1, checkYLoc))
				{
					unitPtr->attack_loc_offset_x = xLoc1-targetLocX;
					unitPtr->attack_loc_offset_y = checkYLoc-targetLocY;
					if(unitPtr->obj_loc_height() > 1)
						checkYLoc += (unitPtr->obj_loc_height()-1);
					if(unitIndex < rangeAttack-1)
						unitPtr = arrayForRangeAttack[++unitIndex];
					else
						break;
				}
			}
		}

		if(unitIndex < rangeAttack)
		{
			for(checkXLoc=xLoc1; checkXLoc<=xLoc2; checkXLoc++)
			{
				if(unitPtr->can_move(checkXLoc, yLoc2))
				{
					unitPtr->attack_loc_offset_x = checkXLoc-targetLocX;
					unitPtr->attack_loc_offset_y = yLoc2-targetLocY;
					if(unitPtr->obj_loc_width() > 1)
						checkXLoc+= (unitPtr->obj_loc_width()-1);
					if(unitIndex < rangeAttack-1)
						unitPtr= arrayForRangeAttack[++unitIndex];
					else
						break;
				}
			}
		}
		
		if(unitIndex < rangeAttack)
		{
			for(checkYLoc=yLoc1+1; checkYLoc<yLoc2; checkYLoc++)
			{
				if(unitPtr->can_move(xLoc2, checkYLoc))
				{
					unitPtr->attack_loc_offset_x = xLoc2-targetLocX;
					unitPtr->attack_loc_offset_y = checkYLoc-targetLocY;
					if(unitPtr->obj_loc_height() > 1)
						checkYLoc+=(unitPtr->obj_loc_height()-1);
					if(unitIndex < rangeAttack-1)
						unitPtr = arrayForRangeAttack[++unitIndex];
					else
						break;
				}
			}
		}
		if(unitIndex < rangeAttack)
		{
			for(; unitIndex<rangeAttack; unitIndex++)
			{
				unitPtr = arrayForRangeAttack[unitIndex];
				//--settting attack_loc_offset_? to 0 will make them cannot attack --//
				unitPtr->attack_loc_offset_x = 0;
				unitPtr->attack_loc_offset_y = 0;
			}
		}
	}
	
	//---- finding a good location for the units undergoing close attack -----//
	if(closeAttack)
	{
		unitIndex = 0;
		unitPtr = arrayForCloseAttack[unitIndex];

		if((testLocY=targetLocY-maxHeight) >= 0) //has top edge
		{
			
			w = unitPtr->obj_loc_width();
			while(w>=0)
			{
				if(targetLocX >= w)
				{
					index = -w;
					break;
				}
				w--;
			}
			err_when(index>0);

			for(; index<targetWidth; index++)
			{
				if(unitPtr->can_move(targetLocX+index, testLocY))
				{
					unitPtr->attack_loc_offset_x = index;
					unitPtr->attack_loc_offset_y = -maxHeight;
					if(unitPtr->obj_loc_width() > 1)
						index += (unitPtr->obj_loc_width()-1);
					if(unitIndex < closeAttack-1)
						unitPtr = arrayForCloseAttack[++unitIndex]; //get_next_unit
					else 
						break;
				}
			}
		}
		if((unitIndex < closeAttack) && ((testLocX = targetLocX + targetWidth) <= MAX_WORLD_X_LOC-maxWidth)) //has right edge
		{
			h = unitPtr->obj_loc_height();
			while(h>=0)
			{
				if(targetLocY >= h)
				{
					index = -h;
					break;
				}
				h--;
			}
			err_when(index>0);
			
			for(; index<targetHeight; index++)
			{
				if(unitPtr->can_move(testLocX, targetLocY+index))
				{
					unitPtr->attack_loc_offset_x = targetWidth;
					unitPtr->attack_loc_offset_y = index;
					if(unitPtr->obj_loc_height() > 1)
						index += (unitPtr->obj_loc_height()-1);
					if(unitIndex < closeAttack-1)
						unitPtr = arrayForCloseAttack[++unitIndex]; //get next unit
					else
						break;
				}
			}
		}
		if((unitIndex < closeAttack) && ((testLocY = targetLocY + targetHeight) <= MAX_WORLD_Y_LOC-maxHeight)) //has bottom edge
		{
			w = unitPtr->obj_loc_width();
			while(w>=0)
			{
				if(targetLocX+targetWidth<=MAX_WORLD_X_LOC-w)
				{
					index = targetWidth-(unitPtr->obj_loc_width()-w);
					break;
				}
				w--;
			}

			for(; index>=0; index--)
			{
				if(unitPtr->can_move(targetLocX+index, testLocY))
				{
					unitPtr->attack_loc_offset_x = index;
					unitPtr->attack_loc_offset_y = targetHeight;
					if(unitIndex < closeAttack-1)
					{
						unitPtr = arrayForCloseAttack[++unitIndex];
						if(unitPtr->obj_loc_width() > 1)
							index -= (unitPtr->obj_loc_width()-1);
					}
					else
						break;
				}
			}
		}
		if(unitIndex < closeAttack && ((testLocX = targetLocX-maxWidth) >=0 )) //has left edge
		{

			h = unitPtr->obj_loc_height();
			while(h>=0)
			{
				if(targetLocY+targetHeight<=MAX_WORLD_Y_LOC-h)
				{
					index = targetHeight-(unitPtr->obj_loc_height()-h);
					break;
				}
				h--;
			}
			
			for(; index>=0; index--)
			{
				if(unitPtr->can_move(testLocX, targetLocY+index)) 
				{
					unitPtr->attack_loc_offset_x = -1;
					unitPtr->attack_loc_offset_y = index;
					if(unitIndex < closeAttack-1)
					{
						unitPtr = arrayForCloseAttack[++unitIndex];
						if(unitPtr->obj_loc_height() > 1)
							index -= (unitPtr->obj_loc_height()-1);
					}
					else
						break;
				}
			}
		}

		//----for those who cannot find a good position, cannot attack
		//---- setting the attack_loc_offset_? to 0 means they cannot attack -----//
		if(unitIndex < closeAttack)
		{
			while(unitIndex < closeAttack-1)
			{
				unitPtr->attack_loc_offset_x = 0;
				unitPtr->attack_loc_offset_y = 0;
				unitPtr = arrayForCloseAttack[++unitIndex];
			}
			unitPtr->attack_loc_offset_x = 0;
			unitPtr->attack_loc_offset_y = 0;
		}
	}
	*/
	cluster_units_for_attack(targetObjRecno, targetLocX, targetLocY, targetWidth, targetHeight);	
	/*		
	if(arrayForRangeAttack) 
		mem_del(arrayForRangeAttack);
	if(arrayForCloseAttack)
		mem_del(arrayForCloseAttack);
	*/
}