Exemple #1
0
int Unit::think_normal_human_action()
{
	if( home_camp_firm_recno )
		return 0;

	//-- if we also don't have any existing camps in this region --//

	Nation* nationPtr = nation_array[nation_recno];

	if( nationPtr->ai_camp_count==0 ||
		 nationPtr->total_camp_unit_space(0) <= nationPtr->total_unit_count )	// If there are more units than the existing forts can hold
	{
		if( ai_build_firm() )
			return 1;
	}

	//--- the following are actions that are only performed if the unit is not led by a commander ---//

	if( leader_unit_recno &&
		 unit_array[leader_unit_recno]->is_visible() )		// if the unit is led by a commander, let the commander makes the decision. If the leader has been assigned to a firm, don't consider it as a leader anymore
	{
		return 0;
	}

	err_when( !race_id );
	err_when( !nation_recno );

	//--- if this is a military unit, think about assigning it to a camp or fort ---//

	if( !is_civilian() )
	{
		if( think_assign_soldier_to_camp() )
			return 1;
	}
	else
	{
		if( think_assign_human_to_town() )
			return 1;
	}

	return 0;
}
Exemple #2
0
//--------- Begin of function Unit::can_succeed_king ---------//
//
int Unit::can_succeed_king()
{
	if( !nation_recno || !race_id )
		return 0;

	Nation* nationPtr = nation_array[nation_recno];

	if( nationPtr->king_unit_recno )	// the king is still alive
		return 0;

	if( nationPtr->is_human() )
	{
		//-- only the nation is a human nation, only human military unit can succeed the king --//

		return is_human() && !is_civilian();
	}
	else
	{
		return monster_res[ nationPtr->monster_id() ]->unit_id == unit_id;
	}
}
Exemple #3
0
//--------- Begin of function Unit::set_rank ---------//
//
// Only if the unit has leadership skill, it can be a general or king.
//
void Unit::set_rank(int rankId)
{
	err_when( !race_id );

	if( rank_id == rankId )
		return;

   err_when( unit_mode != UNIT_MODE_REBEL && rankId >= RANK_GENERAL && is_civilian() );

   //------- promote --------//

   if( rankId > rank_id )
		change_loyalty(PROMOTE_LOYALTY_INCREASE);

	//------- demote -----------//

	else if( rankId < rank_id && rank_id != RANK_KING )      // no decrease in loyalty if a spy king hands his nation to his parent nation and become a general again
		change_loyalty(-DEMOTE_LOYALTY_DECREASE);

	//---- update nation_general_count_array[] ----//

	if( nation_recno )
	{
		UnitInfo* unitInfo = unit_res[unit_id];

		if( rank_id == RANK_GENERAL )    // if it was a general originally
			unitInfo->dec_nation_general_count(nation_recno);

		if( rankId == RANK_GENERAL )     // if the new rank is general
			unitInfo->inc_nation_general_count(nation_recno);

		//------ if demote a king to a unit ------//

		if( rank_id == RANK_KING && rankId != RANK_KING )
			unitInfo->inc_nation_unit_count(nation_recno);     // since kings are not included in nation_unit_count, when it is no longer a king, we need to re-increase it.

		//------ if promote a unit to a king ------//

		if( rank_id != RANK_KING && rankId == RANK_KING )
			unitInfo->dec_nation_unit_count(nation_recno);     // since kings are not included in nation_unit_count, we need to decrease it
	}

	//----- reset leader_unit_recno if demote a general to soldier ----//

	if( rank_id == RANK_GENERAL && rankId == RANK_SOLDIER )
	{
		//----- reset leader_unit_recno of the units he commands ----//

		for( int i=unit_array.size() ; i>0 ; i-- )
		{
			Unit* unitPtr = (Unit*) unit_array.get_ptr(i);		// don't use is_deleted() as it filters out units that are currently dying 

			if( unitPtr && unitPtr->leader_unit_recno == sprite_recno )
			{
				unitPtr->leader_unit_recno = 0;
//				unitPtr->team_id = 0;
			}
		}

		//--------- deinit team_info ---------//

		err_when( !team_info );

		mem_del(team_info);
		team_info = NULL;
//		team_id   = 0;
	}

	//----- if this is a soldier being promoted to a general -----//

	else if( rank_id == RANK_SOLDIER && rankId == RANK_GENERAL )
	{
		//-- if this soldier is formerly commanded by a general, detech it ---//

		if( leader_unit_recno )
		{
			if( !unit_array.is_deleted(leader_unit_recno) )    // the leader unit may have been killed at the same time
			{
				err_when( !unit_array[leader_unit_recno]->team_info );
				unit_array[leader_unit_recno]->team_info->del_member(sprite_recno);
			}

			leader_unit_recno = 0;
		}
	}

	// ###### patch begin Gilbert 27/9 #######//
	// ------- clear royal in campaign mode -----//

	if( rankId == RANK_KING )
	{
		is_royal = 0;
	}
	// ###### patch end Gilbert 27/9 #######//

	//-------------- update AI info --------------//

	if( nation_recno )
	{
		if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
			nation_array[nation_recno]->del_general_info(sprite_recno);

		rank_id = rankId;

		if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
			nation_array[nation_recno]->add_general_info(sprite_recno);
	}
   else
   {
      rank_id = rankId;
   }

   //----- if this is a general/king ------//

   if( rank_id == RANK_GENERAL || rank_id == RANK_KING )
   {
      //--------- init team_info -------//

      if( !team_info )
      {
         team_info = (TeamInfo*) mem_add( sizeof(TeamInfo) );
			memset( team_info, 0, sizeof(TeamInfo) );
      }

      //--- set leadership if this unit does not have any now ----//

		if( skill_level() < 10 )
			skill.set_skill_level( + m.random(40) );
   }

   //------ refresh if the current unit is selected -----//

	if( unit_array.selected_recno == sprite_recno )
		info.disp();
}
Exemple #4
0
//--------- Begin of function Unit::betray ---------//
//
// If this unit is a spy, this function betray() will be
// called by Unit::spy_change_nation() or Firm::capture_firm().
//
// If this is not a spy, this function will only be called
// by think_betray() and other nation deinit functions.
//
int Unit::betray(int newNationRecno)
{
	//----- if this is a spy, call spy_change_nation -----//

	if( spy_recno &&
		 spy_array[spy_recno]->cloaked_nation_recno != newNationRecno ) 	// cloaked_nation_recno == newNationRecno if betray() is called by spy_change_nation() already
	{
		spy_change_nation(newNationRecno, COMMAND_AUTO);
		return 1;
	}

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

	err_when( newNationRecno && nation_array[newNationRecno]->is_human() &&		// monsters in firms should not betray to humans
			    is_monster() && unit_mode == UNIT_MODE_OVERSEE );		

	int unitRecno = sprite_recno;

	err_when( unit_array.is_truly_deleted(unitRecno) );

	err_when( rank_id == RANK_KING );

	if( nation_recno == newNationRecno )
		return 0;

	if( unit_mode == UNIT_MODE_CONSTRUCT_FIRM ||	 // don't change nation when the unit is constructing a firm
		 unit_mode == UNIT_MODE_CONSTRUCT_TOWN ||	 
		 unit_mode == UNIT_MODE_ON_SHIP   )  	// don't change nation when the unit is constructing a firm
	{
		return 0;
	}

	//--- special case: units in Monster Fortress cannot change nation ---//

	if( unit_mode == UNIT_MODE_OVERSEE &&
		 firm_array[unit_mode_para]->firm_id == FIRM_FORTRESS )
	{
		return 0;
	}

	//---------- add news -----------//

	if( nation_recno == nation_array.player_recno ||
		 newNationRecno == nation_array.player_recno )
	{
		//--- if this is a spy, don't display news message for betrayal as it is already displayed in Unit::spy_change_nation() ---//

		if( !spy_recno )
			news_array.unit_betray(sprite_recno, newNationRecno);
	}

	//------ change nation now ------//

	err_when( unit_array.is_truly_deleted(unitRecno) );

	change_nation(newNationRecno);

	err_when( unit_array.is_truly_deleted(unitRecno) );

	//-------- set the loyalty of the unit -------//

	if( nation_recno )
	{
		Nation* nationPtr = nation_array[nation_recno];

		loyalty = UNIT_BETRAY_LOYALTY + 10 + m.random(20);

		if( nationPtr->reputation > 0 )
			change_loyalty( (int) nationPtr->reputation );

		if( race_res.is_same_race( nationPtr->race_id, race_id ) )
			change_loyalty( 30 );

		err_when( loyalty < 0 || loyalty > 100 );

		update_loyalty();		// update target loyalty
	}
	else  //------ if change to independent rebel -------//
	{
		loyalty = 0;      // no loyalty needed
	}

	//--- if this unit is a general, change nation for the units he commands ---//

	if( rank_id==RANK_GENERAL )
	{
		err_when( !team_info );

		for( int i=0 ; i<team_info->member_count ; i++ )
		{
			int memberUnitRecno = team_info->member_unit_array[i];

			if( memberUnitRecno == unitRecno )		// this is the unit itself
				continue;

			Unit* unitPtr = unit_array[memberUnitRecno];

			if( !unitPtr->is_visible() )
				continue;

			if( unitPtr->spy_recno )		// if the unit is a spy
				unitPtr->spy_change_nation(newNationRecno, COMMAND_AUTO);
			else
				unitPtr->change_nation(newNationRecno);
		}
	}

	err_when( unit_array.is_truly_deleted(unitRecno) );

	//------ go to meet the new master -------//

	if( is_visible() && nation_recno )
	{
		if( !spy_recno || spy_array[spy_recno]->notify_cloaked_nation_flag )
		{
			if( is_civilian() )
				ai_move_to_nearby_town();
			else
				ai_move_to_nearby_firm(FIRM_CAMP, FIRM_FORT);
		}
	}

	err_when( unit_array.is_truly_deleted(unitRecno) );

	return 1;
}
Exemple #5
0
//--------- Begin of function Unit::update_loyalty ---------//
//
// How loyalty of units are updated:
//
// General: in a military camp - updated in FirmCamp::update_loyalty()
//          mobile - no update
//
// Soldiers led by a general: in a military camp - updated in FirmCamp::update_loyalty()
//                            mobile - updated here
//
// Other units: no update.
//
void Unit::update_loyalty()
{
	if( !nation_recno || rank_id==RANK_KING || !race_id )
		return;

	if( unit_mode == UNIT_MODE_CONSTRUCT_FIRM || 		// constructor worker will not change their loyalty when they are in a building
		 unit_mode == UNIT_MODE_CONSTRUCT_TOWN )
	{
		return;
   }

	//--- the loyalty of civilians does not change when they are mobile ---//

	if( is_civilian() )
	{
		target_loyalty = loyalty;
		return;
	}

	//-------- if this is a general ---------//

	Nation* ownNation = nation_array[nation_recno];
	int 	  rc=0;

	if( rank_id==RANK_GENERAL )
	{
		//----- the general's power affect his loyalty ----//

		int targetLoyalty = commander_power();

		//----- the king's race affects the general's loyalty ----//

		if( ownNation->race_id == race_id )
			targetLoyalty += 20;

		//----- the kingdom's reputation affects the general's loyalty ----//

		targetLoyalty += (int)ownNation->reputation/4;

		//--- the king's leadership also affect the general's loyalty -----//

		if( ownNation->king_unit_recno )
			targetLoyalty += unit_array[ownNation->king_unit_recno]->skill_level() / 4;

		//-- if the unit is rewarded less than the amount of contribution he made, he will become unhappy --//

		if( nation_contribution > total_reward*2 )
		{
			int decLoyalty = (nation_contribution - total_reward*2)/2;
			targetLoyalty -= min(50, decLoyalty);		// this affect 50 points at maximum
		}

		targetLoyalty = min( targetLoyalty, 100 );
		target_loyalty = max( targetLoyalty, 0 );

		//----- if this unit is a spy, set its fake loyalty ------//

		if( spy_recno )		// it should never go below the rebel level
			target_loyalty = max( 30+sprite_recno%10, target_loyalty );
	}

	//-------- if this is a soldier ---------//

	else if( rank_id==RANK_SOLDIER )
	{
		if( leader_unit_recno )
		{
			//----------------------------------------//
			//
			// If this soldier is led by a general,
			// the targeted loyalty
			//
			// = race friendliness between the unit and the general / 2
			//   + the leader unit's leadership / 2
			//
			//----------------------------------------//

			if( unit_array.is_deleted(leader_unit_recno) )
			{
				leader_unit_recno = 0;
				return;
			}

			Unit* leaderUnit = unit_array[leader_unit_recno];

			int targetLoyalty = 30 + leaderUnit->skill_level();

			//---------------------------------------------------//
			//
			// Soldiers with higher combat and leadership skill
			// will get discontented if they are led by a general
			// with low leadership.
			//
			//---------------------------------------------------//

			targetLoyalty -= combat_level()/2;
			targetLoyalty -= skill_level();

			if( leaderUnit->rank_id == RANK_KING )
				targetLoyalty += 20;

			if( race_res.is_same_race(race_id, leaderUnit->race_id) )
				targetLoyalty += 20;

			if( targetLoyalty < 0 )
				targetLoyalty = 0;

			targetLoyalty = min( targetLoyalty, 100 );
			target_loyalty = max( targetLoyalty, 0 );
		}
		else
		{
			target_loyalty = 0;
		}
	}

	//--------- update loyalty ---------//

	err_when( target_loyalty < 0 || target_loyalty > 100 );

	if( target_loyalty > loyalty )      // only increase, no decrease. Decrease are caused by events. Increases are made gradually
	{
		int incValue = (target_loyalty - loyalty)/10;

		int newLoyalty = (int) loyalty + max(1, incValue);

		if( newLoyalty > target_loyalty )
			newLoyalty = target_loyalty;

		loyalty = newLoyalty;
	}
	else if( target_loyalty < loyalty )      // only increase, no decrease. Decrease are caused by events. Increases are made gradually
	{
		loyalty--;
	}

	err_when( loyalty < 0 || loyalty > 100 );
}
Exemple #6
0
//--------- Begin of function Unit::disp_unit_profile ---------//
//
// <int> dispY1 - the top y coordination of the info area
// <int> refreshFlag
//
void Unit::disp_unit_profile(int dispY1, int refreshFlag)
{
	//--------- set help parameters --------//

	int x=INFO_X1+4;

	if( mouse.in_area(x, dispY1+3, x+UNIT_LARGE_ICON_WIDTH-1, dispY1+UNIT_LARGE_ICON_HEIGHT+2) )
		help.set_unit_help( unit_id, rank_id, x, dispY1+3, x+UNIT_LARGE_ICON_WIDTH-1, dispY1+UNIT_LARGE_ICON_HEIGHT+2 );

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

	if( refreshFlag != INFO_REPAINT )		// only display in repaint mode
		return;

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

	const char *str=NULL;

	if( race_id )
	{
		if( rank_id == RANK_KING )
		{
			str = _("King");
		}
		else if( rank_id == RANK_GENERAL )
		{
			// ##### patch begin Gilbert 17/2 #####//
			if( unit_mode == UNIT_MODE_REBEL )
				str = _("Rebel Leader");
			else
				str = _("General");
			// ##### patch end Gilbert 17/2 #####//
		}
		else if( unit_mode == UNIT_MODE_DEFEND_TOWN )
		{
			str = _("Defending Villager");
		}
		else if( unit_mode == UNIT_MODE_REBEL )
		{
			str = _("Rebel");
		}
		else if( unit_res[unit_id]->unit_class == UNIT_CLASS_GOD )
		{
			str = _("Greater Being");
		}
		else
		{
			if( should_show_info() )
			{
				switch( skill.skill_id )
				{
					case SKILL_LEADING:
						str = _("Soldier");
						break;

					case SKILL_CONSTRUCTION:
						str  = _("Construction Worker");
						break;

					case SKILL_MINING:
						str = _("Miner");
						break;

					case SKILL_MFT:
						str = _("Worker");
						break;

					case SKILL_RESEARCH:
						str = _("Scientist");
						break;

					case SKILL_SPYING:
						str = _("Spy");
						break;

					default:
						str = _("Peasant");
						break;
				}
			}
			else	//--- don't display too much info on enemy units ---//
			{
				if( skill.skill_id == SKILL_LEADING )
					str = _("Soldier");

				else if( is_civilian() )
					str = _("Civilian");
			}
		}
	}

	//---------------- paint the panel --------------//

	vga_util.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+44);

	vga_front.put_bitmap( x, dispY1+3, unit_res[unit_id]->get_large_icon_ptr(rank_id) );

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

	x += UNIT_LARGE_ICON_WIDTH;

	if( str )
	{
		font_san.center_put( x, dispY1+4, INFO_X2-2, dispY1+21, str );
		font_san.center_put( x, dispY1+22, INFO_X2-2, dispY1+40, unit_name(0) );		// 0-without title
	}
	else
	{
		font_san.center_put( x, dispY1, INFO_X2-2, dispY1+44, unit_name() );		// non-human units
	}
}
Exemple #7
0
//--------- Begin of function Unit::disp_unit_info ---------//
//
// Display the skill information of the people in the town.
//
// <int> 	dispY1		 - the top y coordination of the info area
// <int>    refreshFlag  - refresh flag
//
void Unit::disp_unit_info(int dispY1, int refreshFlag)
{
	#ifdef DEBUG
		if(debug2_enable_flag)
		{
			if(unit_res[unit_id]->unit_class == UNIT_CLASS_MONSTER)
			{
				int 	 x=INFO_X1+4, y=dispY1+20;
				y+=20;
				font_san.field( x, y, " " , x+2, sprite_recno, 1, INFO_X2-2, refreshFlag);
				font_san.field( x+20, y, " " , x+22, next_x_loc(), 1, INFO_X2-2, refreshFlag);
				font_san.field( x+50, y, " " , x+52, next_y_loc(), 1, INFO_X2-2, refreshFlag);
				font_san.field( x+70, y, " " , x+72, nation_recno, 1, INFO_X2-2, refreshFlag);

				font_san.field( x+100, y, " " , x+102, action_mode, 1, INFO_X2-2, refreshFlag);
				font_san.field( x+120, y, " " , x+122, action_para, 1, INFO_X2-2, refreshFlag);
				font_san.field( x+140, y, " " , x+142, action_x_loc, 1, INFO_X2-2, refreshFlag);
				font_san.field( x+160, y, " " , x+162, action_y_loc, 1, INFO_X2-2, refreshFlag);
				y-=20;
				font_san.field( x+100, y, " " , x+102, action_mode2, 1, INFO_X2-2, refreshFlag);
				font_san.field( x+120, y, " " , x+122, action_para2, 1, INFO_X2-2, refreshFlag);
				font_san.field( x+140, y, " " , x+142, action_x_loc2, 1, INFO_X2-2, refreshFlag);
				font_san.field( x+160, y, " " , x+162, action_y_loc2, 1, INFO_X2-2, refreshFlag);
				y-=20;
				font_san.field( x+160, y, " " , x+162, cur_action, 1, INFO_X2-2, refreshFlag);
			}
		}
	#endif

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

	if( !race_id )		// if it's not a human unit, don't display anything
		return;

	if( refreshFlag==INFO_REPAINT )
		vga_util.d3_panel_up( INFO_X1, dispY1, INFO_X2, dispY1+87 );

	int 	 x=INFO_X1+4, y=dispY1+4;
	String str;

	//--------- display loyalty ---------//

	if( rank_id != RANK_KING && (nation_recno || spy_recno) )
	{
		if( spy_recno &&			// only display spy loyalty instead of unit loyalty if this is a spy and this spy is ours
			 true_nation_recno() == nation_array.player_recno )
		{
			font_san.field( x, y, _("Loyalty"), x+92, spy_array[spy_recno]->spy_loyalty, 1, INFO_X2-2, refreshFlag);
		}
		else if( nation_recno )
		{
			info.disp_loyalty( x, y, x+92, loyalty, target_loyalty, nation_recno, refreshFlag );
		}

		y+=16;
	}

	//--------- display combat level ----------//

	font_san.field( x, y, _("Combat") , x+92, skill.combat_level, 1, INFO_X2-2, refreshFlag);

	y+=16;

	//-------- display skill level ---------//

	if( skill.skill_id )
	{
		if( refreshFlag == INFO_REPAINT )
			font_san.field( x, y, skill.skill_des(), x+92, skill.skill_level , 1, INFO_X2-2, refreshFlag);
		else
			font_san.field( x, y, skill.skill_des(), x+92, skill.skill_level , 1, INFO_X2-2, refreshFlag);

		y+=16;
	}

	//------- display spying skill if the unit is a spy -----//

	if( spy_recno && spy_array[spy_recno]->true_nation_recno == nation_array.player_recno )		// only spies of the player's nation can see the spy skill details
	{
		font_san.field( x, y, _("Spying"), x+92, spy_array[spy_recno]->spy_skill, 1, INFO_X2-2, refreshFlag);

		y+=16;
	}

	//--------- display debug info ---------//

	if( !is_civilian() && rank_id != RANK_KING )
		font_san.field( x, y, _("Contribution"), x+92, nation_contribution, 1, INFO_X2-2, refreshFlag);
}
Exemple #8
0
int Unit::think_reward()
{
	Nation* ownNation = nation_array[nation_recno];

	//----------------------------------------------------------//
	// The need to secure high loyalty on this unit is based on:
	// -its skill
	// -its combat level 
	// -soldiers commanded by this unit
	//----------------------------------------------------------//

	if( spy_recno && true_nation_recno() == nation_recno )		// if this is a spy of ours
	{
		return 0;		// Spy::think_reward() will handle this.
	}

	int curLoyalty = loyalty;
	int neededLoyalty;

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

	if( cur_order.ai_action_id )
	{
		neededLoyalty = UNIT_BETRAY_LOYALTY+10;
	}

	//----- otherwise only reward soldiers and generals ------//

	else if( !is_civilian() )		// it is a military unit
	{
		//----- calculate the needed loyalty --------//

		neededLoyalty = commanded_soldier_count()*5 + skill_level();

		if( unit_mode == UNIT_MODE_OVERSEE )		// if this unit is an overseer
		{
			if( loyalty < UNIT_BETRAY_LOYALTY )		// if this unit's loyalty is < betrayel level, reward immediately
			{
				reward(nation_recno);		// reward it immediatley if it's an overseer, don't check ai_should_spend()
				return 1;
			}

			neededLoyalty += 30;
		}

		neededLoyalty = MAX( UNIT_BETRAY_LOYALTY+10, neededLoyalty );		// 10 points above the betray loyalty level to prevent betrayal
		neededLoyalty = MIN( 100, neededLoyalty );
	}
	else
	{
		return 0;
	}

	//------- if the loyalty is already high enough ------//

	if( curLoyalty >= neededLoyalty )
		return 0;

	//---------- see how many cash & profit we have now ---------//

	int rewardNeedRating = neededLoyalty - curLoyalty;

	if( curLoyalty < UNIT_BETRAY_LOYALTY+5 )
		rewardNeedRating += 50;

	if( ownNation->ai_should_spend(rewardNeedRating) )
	{
		reward(nation_recno);
		return 1;
	}

	return 0;
}