Exemplo n.º 1
0
//--------- Begin of function BulletProgram::init ---------//
//
// <char> parentType		- the type of object emits the bullet
// <short> parentRecno	- the recno of the object
// <short> targetXLoc	- the x loc of the target
// <short> targetYLoc	- the y loc of the target
//	<char> targetMobileType - target mobile type
//
void BulletProgram::init(char parentType, short parentRecno, short targetXLoc, short targetYLoc, char targetMobileType)
{
	Bullet::init(parentType, parentRecno, targetXLoc, targetYLoc, targetMobileType);
	cur_step = 0;
	
	BaseObj *baseObjPtr = base_obj_array[parent_base_obj_recno];
	Unit *parentUnit;

	// for fixed total_step of bullet, set sprite.dbf's speed //
	// else total_step = distance to target / unitattk.dbf's bullet_speed //
	
	// start animation	bullet_running		die_animation
	// delay_step			total_step
	// 
	//	bullet_delay in	if sprite.dbf's	no. of frame filled
	// sprite.dbf &		speed > 0, take	in sframe.dbf
	// unitattk.dbf		it else use
	//							distance to 
	//							calculate

	if (sprite_info->speed > 0) 
		total_step = sprite_info->speed;

	if( (parentUnit = baseObjPtr->cast_to_Unit()) )
	{
		// delay obtained from unitattk.dbf //
		AttackInfo* attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack;
		delay_step = attackInfo->bullet_delay;
	}
	else
	{
		// delay obtained from sprite.dbf if the attacker is not a unit //
		delay_step = sprite_info->bullet_delay;
	}
}
Exemplo n.º 2
0
BaseObj::BaseObj(BaseObj *parent,
	         const char *name)
{
   _name = STRDUP(name);
   _displayName = NULL;
   _details = NULL;
   _parent = parent;
   _init_children = false;
   _init_attributes = false;
   _children = NULL;
   _numChildren = 0;
   _numActions = 0;
   _numAttributes = 0;
   _actions = NULL;
   _attributes = NULL;
   _lastActionName = NULL;
   _lastActionOutput = NULL;
   _lastActionStatus = 0;
   AddToParent();
   BaseObj *p = _parent;
   while (p)
    {
      p->NotifyCreate(this);
      p = p->_parent;
    }
}
Exemplo n.º 3
0
BaseObj::~BaseObj()
{
   int i;

   DeleteChildren();
   DeleteFromParent();

   BaseObj *parent = _parent;
   while (parent)
    {
      parent->NotifyDelete(this);
      parent = parent->_parent;
    }

   for (i = 0; i < _numAttributes; i++)
    {
      delete _attributes[i]->ReferenceName;
      delete _attributes[i]->Value;
      delete _attributes[i]->DisplayName;
      delete _attributes[i]->DisplayValue;
      delete _attributes[i]->DefaultValue;
      delete _attributes[i]->DisplayDefaultValue;
      delete _attributes[i]->Help;
      delete _attributes[i]->ContextualHelp;
      delete _attributes[i]->Listing;
      delete _attributes[i]->Dependancies;
      delete _attributes[i];
    }
   delete []_attributes;
   for (i = 0; i < _numActions; i++)
    {
      delete _actions[i]->ReferenceName;
      delete _actions[i]->DisplayName;
      delete _actions[i]->Nmemonic;
      delete _actions[i]->AcceleratorText;
      delete _actions[i]->Accelerator;
      delete _actions[i]->Help;
      delete _actions[i]->ContextualHelp;
      delete _actions[i]->Dependancies;
      delete _actions[i];
    }
   delete []_actions;
   delete []_children;
   free(_lastActionName);
   delete [] _lastActionOutput;
   free(_details);
   free(_displayName);
   free(_name);
}
Exemplo n.º 4
0
void Swarm::updateSwarm(real dt, SwarmNode* next, BaseObj& collision, std::vector<Bullet*> bulletList)
{
	if (next->data.m_bAlive) {
		XMVECTOR pos = XMLoadFloat3(&next->data.m_vPos);
		XMVECTOR playerTarget = XMLoadFloat3(&m_pLead->data.m_vTarget);
		XMVECTOR distance = XMVector3Length(pos - playerTarget);

		if (XMVectorGetX(distance) < 120.0f || XMVectorGetY(distance) < 120.0f || false == m_pLead->data.m_bAlive)
			next->data.m_vTarget = m_pLead->data.m_vTarget;
		else
			next->data.m_vTarget = next->parent->data.m_vPos;

		// check if we hit the player
		next->data.update(dt);
		next->data.checkCollision(collision);

		if (next->data.m_bHit)
			next->data.reduceHealth(collision.getDamage());

		if (next->data.m_fLife < 0.0f) {
			dynamic_cast<Player&>(collision).increasePoints(5.0f);
			collision.reduceHealth(next->data.m_fDamage);
			next->data.m_bAlive = false;
			//collision.increasePoints(20.0f);
		}

		// check if a bullet hit the alien
		for (unsigned int i = 0; i < bulletList.size(); ++i) {
			next->data.checkCollision(*bulletList[i]);

			if (next->data.m_bHit && next->data.m_bAlive) {
				next->data.reduceHealth(bulletList[i]->getDamage());
				bulletList[i]->setState(Bullet::BState_Hit);
			}
			
			if (next->data.m_fLife < 0.0f) {
				dynamic_cast<Player&>(collision).increasePoints(25.0f);
				next->data.m_bAlive = false;
			}
		}
	}

	if (next->ltChild)
		updateSwarm(dt, next->ltChild, collision, bulletList);
	if (next->rtChild)
		updateSwarm(dt, next->rtChild, collision, bulletList);
}
Exemplo n.º 5
0
//--------- Begin of function Sprite::process_die --------//
//
// return : <int> 1 - dying animation completes.
//					   0 - still dying
// 
int Sprite::process_die()
{
	//--------- next frame ---------//

//	if( sys.frame_count%2 == 0 )
//	{
		if (cur_frame == 1)
		{
			BaseObj *baseObj = base_obj_array[base_obj_recno];
			Unit* unitPtr = baseObj->cast_to_Unit();
			if (unitPtr)
				unitPtr->add_die_effect();
		}
		se_res.sound(cur_x_loc(), cur_y_loc(), cur_frame, 'S',sprite_id,"DIE");
		if( ++cur_frame > sprite_info->die.frame_count )
			return 1;
//	}

	return 0;
}
Exemplo n.º 6
0
//--------- Begin of function UnitOrder::set ---------//
//
void UnitOrder::set(int newMode, int newPara, int newXLoc, int newYLoc)
{
	mode  = newMode;
	para  = newPara;
	loc_x = newXLoc;
	loc_y = newYLoc;

	ai_action_id = 0;
	name_id = 0;

	//--- set name_id to Unit::name_id if the order is attacking a unit. This is for verifying attack target ---//

	if( mode==UNIT_ATTACK )
	{
		BaseObj* targetObj = base_obj_array[para];

		if( targetObj->obj_type == OBJ_UNIT )
			name_id = targetObj->cast_to_Unit()->name_id;
	}
}
Exemplo n.º 7
0
// --------- begin of function BulletHoming::init --------//
void BulletHoming::init(char parentType, short parentRecno, short targetXLoc, short targetYLoc, char targetMobileType)
{
	Bullet::init(parentType, parentRecno, targetXLoc, targetYLoc, targetMobileType);

	// ------- find the maximum range --------//

	BaseObj *baseObjPtr = base_obj_array[parent_base_obj_recno];
	if( baseObjPtr->cast_to_Unit() )
	{
		Unit *parentUnit = base_obj_array[parent_base_obj_recno]->cast_to_Unit();
		AttackInfo* attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack;
		speed = attackInfo->bullet_speed;
		max_step = char((attackInfo->attack_range * LOCATE_WIDTH + speed-1)/ speed);
	}
	else if( baseObjPtr->cast_to_Firm() && baseObjPtr->cast_to_Firm()->cast_to_FirmFort() )
	{
		FirmFort *firmFort = baseObjPtr->cast_to_Firm()->cast_to_FirmFort();
		speed = firmFort->bullet_speed();
		max_step = 100;		// unlimited range
	}
	else
	{
		err_here();
	}

	//--------- keep backup of centre of the bullet ---------//
	SpriteFrame *spriteFrame = cur_sprite_frame();

	// origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap //
	origin_x += spriteFrame->offset_x + spriteFrame->width/2;
	origin_y += spriteFrame->offset_y + spriteFrame->height/2;
	origin2_x = origin_x; 
	origin2_y = origin_y;
	go_x += spriteFrame->offset_x + spriteFrame->width/2;
	go_y += spriteFrame->offset_y + spriteFrame->height/2;

	// ------- find the target_type and target_recno ------//

	Location *locPtr = world.get_loc(targetXLoc, targetYLoc);
	target_base_obj_recno = locPtr->base_obj_recno(targetMobileType);
}
Exemplo n.º 8
0
void Swarm::updateSwarm(Fugui::real dt, BaseObj& collision, std::vector<Bullet*> bulletList)
{
	if (m_pLead) {
		if (m_pLead->data.m_bAlive) {
			m_pLead->data.update(dt);
			m_pLead->data.checkCollision(collision);

			if (m_pLead->data.m_bHit)
				m_pLead->data.m_fLife -= collision.getDamage();

			if (m_pLead->data.m_fLife < 0.0f) {
				dynamic_cast<Player&>(collision).increasePoints(5.0f);
				m_pLead->data.m_bAlive = false;
				//collision.increasePoints(20.0f);
			}
		}

		// check if a bullet hit the alien
		for (unsigned int i = 0; i < bulletList.size(); ++i) {
			m_pLead->data.checkCollision(*bulletList[i]);

			if (m_pLead->data.m_bHit && m_pLead->data.m_bAlive) {
				m_pLead->data.reduceHealth(bulletList[i]->getDamage());
				bulletList[i]->setState(Bullet::BState_Hit);
			}

			if (m_pLead->data.m_fLife < 0.0f) {
				dynamic_cast<Player&>(collision).increasePoints(25.0f);
				m_pLead->data.m_bAlive = false;
			}
		}

		if (m_pLead->ltChild) 
			updateSwarm(dt, m_pLead->ltChild, collision, bulletList);
		if (m_pLead->rtChild)
			updateSwarm(dt, m_pLead->rtChild, collision, bulletList);
	}
}
Exemplo n.º 9
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 );
	}
}
Exemplo n.º 10
0
//--------- Begin of function Unit::process_ai --------//
//
// [int] forceExecute - whether force execute all AI functions
//								without checking day interavals.
//							   (default: 0)
//
void Unit::process_ai()
{
	if( unit_mode )		// let functions in OUN_MODE.CPP process units in specific modes 
		return;

	err_when( !nation_recno );

	//------ the behavior_mode of AI units is aggressive ------//

	behavior_mode = UNIT_AGGRESSIVE;

	//------- handle Seek Path failures ------//

	if( ai_handle_seek_path_fail() )
		return;

	//--- if it's a spy from other nation, don't control it ---//

	if( spy_recno && true_nation_recno() != nation_recno )
	{
		//--- a random chance of the AI catching the spy and resign it ---//

		if( is_visible() && misc.random(365 * FRAMES_PER_DAY)==0 )		// if the unit stay outside for one year, it will get caught
		{
			resign(COMMAND_AI);
			return;
		}

		if( !spy_array[spy_recno]->notify_cloaked_nation_flag )		// if notify_cloaked_nation_flag is 1, the nation will take it as its own spies
			return;
	}

	//----- think about rewarding this unit -----//

	if( race_id && rank_id != RANK_KING &&
		 info.game_date%5 == sprite_recno%5 )
	{
		think_reward();
	}

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

	if( !is_visible() )
		return;

	//----- think about using items -------//

	if( think_use_item() )
		return;

	//---- King flees under attack or surrounded by enemy ---//

	if( race_id && rank_id==RANK_KING )
	{
		if( think_king_flee() )
			return;
	}

	//---- General flees under attack or surrounded by enemy ---//

	if( race_id && rank_id==RANK_GENERAL &&
		 info.game_date%7 == sprite_recno%7 )
	{
		if( think_general_flee() )
			return;
	}

	//---- stop attacking a town with zero resistance ----//

	if( cur_order.mode==UNIT_ATTACK && nation_recno)
	{
		if( !base_obj_array.is_deleted(cur_order.para) )
		{
			BaseObj* baseObj = base_obj_array[cur_order.para];

			if( baseObj->cast_to_Town() && baseObj->cast_to_Town()->nation_recno==0
				 &&  baseObj->cast_to_Town()->resistance(nation_recno) < 1 )
			{
				stop_order();
				return;
			}
		}
	}

	//------ if the unit is not stop right now ------//

	if( !is_all_stop() )
	{
		think_stop_chase();
		return;
	}

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

	if( mobile_type==UNIT_LAND )
	{
		if( ai_escape_fire() )
			return;
	}

	//---------- if this is your spy --------//

	if( spy_recno && true_nation_recno()==nation_recno )
		think_spy_action();

	//----- if this unit is on a attack mission ----//

	if( is_all_stop() && in_ai_attack_mission )
	{
		if( ai_attack_next_target() )
			return;
	}

	//------ if this unit is from a camp --------//

	if( home_camp_firm_recno )
	{
		FirmCamp* firmCamp;
		FirmMonsterFortress* firmMonsterFortress;

		int   rc = 0;

		if( firm_array.is_deleted(home_camp_firm_recno) )
		{
			rc = 0;
		}
		if( (firmCamp = firm_array[home_camp_firm_recno]->cast_to_FirmCamp()) )
		{
			if( rank_id == RANK_SOLDIER )
				rc = firmCamp->soldier_count < MAX_SOLDIER;
			else
				rc = !firmCamp->overseer_recno;
		}
		else if( (firmMonsterFortress = firm_array[home_camp_firm_recno]->cast_to_FirmMonsterFortress()) )
		{
			rc = (unit_id == firmMonsterFortress->support_unit_id 
				&& !firmMonsterFortress->is_extra_builder_full()) 
				|| !firmMonsterFortress->is_soldier_full();		
		}
		else
		{
			err_here();
		}

		if( rc )
		{
			if( return_camp() )
				return;
		}

		home_camp_firm_recno = 0;		// the camp is already occupied by somebody
	}

	//------- if the unit is idle ------------//

	if( is_all_stop() )
	{
		if( race_id && rank_id==RANK_KING )
		{
			if( is_human() )
				think_king_action();
			else
				think_normal_monster_action();
		}
		else if( race_id && rank_id==RANK_GENERAL )
		{
			think_general_action();
		}
		else
		{
			int unitClass = unit_res[unit_id]->unit_class;

         //------ if this unit is a weapon ------//

			// ######### begin Gilbert 24/3 ########//
			// BUGHERE : monster weapon was UNIT_CLASS_MONSTER but now UNIT_CLASS_MONS_WEAPON
			if( unitClass == UNIT_CLASS_WEAPON || unitClass == UNIT_CLASS_MONS_WEAPON )
			// ######### end Gilbert 24/3 ########//
			{
				if( info.game_date%15 == sprite_recno%15 )	// don't call too often as the action may fail and it takes a while to call the function each time
				{
					think_weapon_action();	//-- ships AI are called in UnitMarine --//
				}
			}

			//------ if this unit is a monster ------//

			else if( unitClass == UNIT_CLASS_MONSTER ||
					 unitClass == UNIT_CLASS_INSECT ||
					 unitClass == UNIT_CLASS_ANIMAL )
			{
				//--- if previous attempts for new action failed, don't call think_normal_human_action() so frequently then ---//

				if( ai_no_suitable_action )
				{
					if( info.game_date%15 != sprite_recno%15 )	// don't call too often as the action may fail and it takes a while to call the function each time
						return;
				}

				if( !think_normal_monster_action() )
				{
					ai_no_suitable_action = true; 	// set this flag so think_normal_human_action() won't be called continously
					ai_move_to_nearby_firm(FIRM_LAIR);
				}
			}

			//------ if this unit is a human ------//

			else if( unitClass == UNIT_CLASS_HUMAN )
			{
				//--- if previous attempts for new action failed, don't call think_normal_human_action() so frequently then ---//

				if( ai_no_suitable_action )
				{
					if( info.game_date%15 != sprite_recno%15 )	// don't call too often as the action may fail and it takes a while to call the function each time
						return;
				}

				if( !think_normal_human_action() )
				{
					ai_no_suitable_action = true; 	// set this flag so think_normal_human_action() won't be called continously

//					if( !leader_unit_recno )		// only when the unit is not led by a commander
//						resign(COMMAND_AI);
//					else
						ai_move_to_nearby_town();
				}
			}

			//---- if this unit is a wagon -----//

			else if( unitClass == UNIT_CLASS_WAGON )
			{
				think_assign_human_to_town();
			}
		}
	}
}
Exemplo n.º 11
0
// --------- begin of function BulletHoming::process_move --------//
void BulletHoming::process_move()
{
	int actualStep = total_step;


	if( base_obj_array.is_deleted(target_base_obj_recno) )
	{
		target_base_obj_recno = 0;
	}
	else
	{
		BaseObj *baseObj = base_obj_array[target_base_obj_recno];
		Unit *unitPtr = baseObj->cast_to_Unit();

		if( unitPtr && unitPtr->is_visible() )
		{
			// ---- calculate new target_x_loc, target_y_loc -----//	

			target_x_loc = unitPtr->next_x_loc();
			target_y_loc = unitPtr->next_y_loc();

			// ---- re-calculate go_x, go_y  ------//
			// go_x/y and origin2_x/y are pointing at the centre of the bullet bitmap
			// it is different from Bullet
			go_x = unitPtr->cur_x + LOCATE_WIDTH / 2;
			go_y = unitPtr->cur_y + LOCATE_HEIGHT /2;

			//---------- set bullet movement steps -----------//
			SpriteFrame *spriteFrame = cur_sprite_frame();
			int adjX = spriteFrame->offset_x+spriteFrame->width/2;
			int adjY = spriteFrame->offset_y+spriteFrame->height/2;

			int xStep 	= abs(go_x - (cur_x+adjX))/speed;
			int yStep 	= abs(go_y - (cur_y+adjY))/speed;
			total_step  = cur_step +  MAX(xStep, yStep);

			// a homing bullet has a limited range, if the target go outside the
			// the limit, the bullet can't attack the target
			// in this case, actualStep is the number step from the source
			// to the target; total_step is the max_step
			// otherwise, actualStep is as same as total_step
			
			actualStep = total_step;
			if( total_step > max_step )
			{
				total_step = max_step;
				// target_x_loc and target_y_loc is limited also
				target_x_loc = (cur_x + adjX) + (int)(go_x-(cur_x+adjX)) / (actualStep - total_step) / LOCATE_WIDTH;
				target_x_loc = (cur_y + adjY) + (int)(go_y-(cur_y+adjY)) / (actualStep - total_step) / LOCATE_HEIGHT;
			}
		}
	}

//	origin2_x = origin_x;
//	origin2_y = origin_y;

	// origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap //
	SpriteFrame *spriteFrame = cur_sprite_frame();
	short adjX = spriteFrame->offset_x + spriteFrame->width/2;
	short adjY = spriteFrame->offset_y + spriteFrame->height/2;
	origin_x = cur_x + adjX;
	origin_y = cur_y + adjY;

	cur_x = origin_x + (int)(go_x-origin_x) / (actualStep + 1 - cur_step);
	cur_y = origin_y + (int)(go_y-origin_y) / (actualStep + 1 - cur_step);
	// cur_x, cur_y is temporary pointing at the centre of bullet bitmap

	// detect changing direction
	if( cur_step > 3 )	// not allow changing direction so fast
		set_dir(origin2_x, origin2_y, cur_x, cur_y);

	// change cur_x, cur_y to bitmap reference point
	spriteFrame= cur_sprite_frame();
	adjX = spriteFrame->offset_x + spriteFrame->width/2;
	adjY = spriteFrame->offset_y + spriteFrame->height/2;
	cur_x -= adjX;
	cur_y -= adjY;

	cur_step++;

	//------- update frame id. --------//

	if( ++cur_frame > cur_sprite_move()->frame_count )
		cur_frame = 1;

	//----- if the sprite has reach the destintion ----//

	if( cur_step > total_step )
	{
		check_hit();

		cur_action = SPRITE_DIE;		// Explosion
		// ###### begin Gilbert 17/5 ########//
		// if it has die frame, adjust cur_x, cur_y to be align with the target_x_loc, target_y_loc
		if( sprite_info->die.first_frame_recno )
		{
			next_x = cur_x = target_x_loc * LOCATE_WIDTH;
			next_y = cur_y = target_y_loc * LOCATE_HEIGHT;
		}
		// ###### end Gilbert 17/5 ########//
		cur_frame = 1;
	}
	// change of total_step may not call warn_target, so call more warn_target
	else if( total_step - cur_step <= 1 )
	{
		warn_target();
	}
}
Exemplo n.º 12
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);
	}
}
Exemplo n.º 13
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);
	*/
}
Exemplo n.º 14
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;
}