Пример #1
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);
	*/
}
Пример #2
0
// ----- begin of function ScenarioEditor::disp_monster_view ------//
//
void ScenarioEditor::disp_monster_view()
{
	if( power.command_id )
		return;

	int drawMarker = 0;
	int validAction = 0;
	int markerX1, markerY1, markerX2, markerY2;

	int xLoc, yLoc;
	char mobileType;

	if( mouse.in_area(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2) )
	{
		// destruction marker if there is a human

		Location *locPtr = power.test_detect(mouse.cur_x, mouse.cur_y, &mobileType, &xLoc, &yLoc);
		
		if( locPtr && locPtr->base_obj_recno() )
		{
			BaseObj *baseObj = base_obj_array[locPtr->base_obj_recno()];
			drawMarker = 1;
			validAction = 1;
			markerX1 = baseObj->obj_loc_x1();
			markerY1 = baseObj->obj_loc_y1();
			markerX2 = baseObj->obj_loc_x2();
			markerY2 = baseObj->obj_loc_y2();
		}

		// construction marker

		else if( world.zoom_matrix->get_detect_location(mouse.cur_x, mouse.cur_y, &xLoc, &yLoc, NULL) )
		{
			locPtr = world.get_loc( xLoc, yLoc );

			if( unit_or_struct == 0 && !vbrowse_unit_id.none_record )
			{
				// put unit monster_unit_id_array[monster_unit_id_browse_recno-1]
				// on (xLoc, yLoc)
				int unitId = monster_unit_id_array[monster_unit_id_browse_recno-1];
				UnitInfo *unitInfo = unit_res[unitId];
				SpriteInfo *spriteInfo = sprite_res[unitInfo->sprite_id];
				if( world.check_unit_space(xLoc, yLoc, 
					xLoc+spriteInfo->loc_width-1, yLoc+spriteInfo->loc_height-1, unitInfo->mobile_type) )
				{
					validAction = 1;
				}
				markerX1 = xLoc;
				markerY1 = yLoc;
				markerX2 = xLoc + spriteInfo->loc_width -1;
				markerY2 = yLoc + spriteInfo->loc_height -1;
				drawMarker = markerX2 < MAX_WORLD_X_LOC && markerY2 < MAX_WORLD_Y_LOC;
			}
			else if( unit_or_struct == 1 && !vbrowse_firm_build.none_record )
			{
				err_when( monster_firm_group_array[monster_firm_group_browse_recno-1] == 0 );
				// put firm group monster_firm_group_array[monster_firm_group_browse_recno]
				// on (xLoc, yLoc)

				FirmGroup *firmGroup = firm_res.get_group(monster_firm_group_array[monster_firm_group_browse_recno-1]);
				if( world.can_build_firm( xLoc, yLoc, firmGroup->firm_id, 0) )
				{
					validAction = 1;
				}
				markerX1 = xLoc;
				markerY1 = yLoc;
				markerX2 = xLoc + firm_res[firmGroup->firm_id]->loc_width - 1;
				markerY2 = yLoc + firm_res[firmGroup->firm_id]->loc_height - 1;
				drawMarker = markerX2 < MAX_WORLD_X_LOC && markerY2 < MAX_WORLD_Y_LOC;
			}
		}
	}

	// ------ draw marker -------//

	if( drawMarker )
	{
		draw_marker( validAction, markerX1, markerY1, markerX2, markerY2 );
	}
}
Пример #3
0
//----- Begin of function Nation::consider_military_aid -----//
//
int Nation::consider_military_aid(TalkMsg* talkMsg)
{
	Nation*			 fromNation   = nation_array[talkMsg->from_nation_recno];
	NationRelation* fromRelation = get_relation(talkMsg->from_nation_recno);

	//----- don't aid too frequently ------//

	if( info.game_date < fromRelation->last_military_aid_date + 200 - pref_allying_tendency )
		return 0;

	//------- only when the AI relation >= 60 --------//

	if( fromRelation->ai_relation_level < 60 )
		return 0;

	//--- if the requesting nation is not at war now ----//

	if( !fromNation->is_at_war() )
		return 0;

	//---- can't aid if we are at war ourselves -----//

	if( is_at_war() )
		return 0;

	//--- if the nation is having a financial difficulty, it won't agree ---//

	if( cash < 2000 * pref_cash_reserve / 100  )
		return 0;

	//----- can't aid if we are too weak ourselves ---//

	if( ai_general_count*10 + total_human_count + total_monster_count
		 < 100-pref_military_courage/2 )
	{
		return 0;
	}

	//----- see what units are attacking the nation -----//

	if( unit_array.is_deleted(fromNation->last_attacker_obj_recno) )
		return 0;

	BaseObj* baseObj = base_obj_array[ fromNation->last_attacker_obj_recno ];

	if( baseObj->nation_recno == nation_recno )		// if it's our own units
		return 0;

	if( baseObj->nation_recno == 0 )
		return 0;

	if( !baseObj->is_visible() )
		return 0;

	//------ only attack if it's a common enemy to us and our ally -----//

	if( get_relation(baseObj->nation_recno)->status != RELATION_HOSTILE )
		return 0;

	//------- calculate the combat level of the target units there ------//

	int hasWar;

	int targetCombatLevel = mobile_defense_combat_level( baseObj->obj_loc_x1(), baseObj->obj_loc_y1(),
									baseObj->nation_recno, 0, hasWar );

	if( ai_attack_target(baseObj->obj_loc_x1(), baseObj->obj_loc_y1(),
		 targetCombatLevel, 0, 1 ) )		//0-not defense mode, 1-just move to flag
	{
		fromRelation->last_military_aid_date = info.game_date;
		return 1;
	}

	return 0;
}