Пример #1
0
//-------- Begin of function Trainee::basic_train ------//
//
// Non-basic training: train the unit if it has potential.
//
void Trainee::basic_train(int firmRecno)
{
	int trainedFlag=0;

	//------ train spy skill --------//

	if( train_spy_potential && spy_skill < BASIC_SKILL_TRAIN )
	{
		spy_skill += 1;

		if( spy_skill > MAX_SKILL_TRAIN )
			spy_skill = MAX_SKILL_TRAIN;

		trainedFlag=1;
	}

	//------ train combat --------//

	if( train_type == TRAIN_UNIT_CIVILIAN )
	{
		if( combat_level() < CITIZEN_COMBAT_LEVEL )
		{
			skill.inc_combat_level(1);
			trainedFlag=1;
		}
	}
	else		//----- military unit -----//
	{
		int basicCombatLevel = BASIC_COMBAT_TRAIN;
		int nationRecno = firm_array[firmRecno]->nation_recno;
		// ##### patch begin Gilbert 16/2 ######//
		// if( nationRecno && race_id == RACE_ROMAN 
		//	&& god_res[GOD_ROMAN]->nation_prayer_count(nationRecno) > 0 )
		if( nationRecno && god_res[GOD_ROMAN]->nation_prayer_count(nationRecno) > 0 )
		// ##### patch end Gilbert 16/2 ######//
		{
			basicCombatLevel += BASIC_COMBAT_TRAIN / 2;		// roman can train to combat level 30
		}

		if( train_combat_potential && combat_level() < basicCombatLevel )
		{
			float incPoints = (float) basicCombatLevel / unit_res[unit_id]->build_days;

			skill.inc_combat_level(incPoints);
			trainedFlag=1;
		}
	}

	//------ train leadership --------//

	if( train_skill_potential && skill_level() < BASIC_SKILL_TRAIN )
	{
		skill.inc_skill_level(1);
		trainedFlag=1;
	}

	if( !trainedFlag )                        // this unit has completed training
		is_under_training = 0;
}
Пример #2
0
//--------- Begin of function Unit::set_combat_level ---------//
//
// <int> combatLevel   new combat level or -1 for current combat level
//                     so as to update unit attribute of that combat level
void Unit::set_combat_level(int combatLevel)
{
	// ##### begin Gilbert 4/11 ######//
	if( combatLevel == -1 )		// update unit attribute of that combat level
		combatLevel = skill.actual_combat_level(NULL);		// get original combat
	// ##### end Gilbert 4/11 ######//

	err_when( combatLevel<=0 || combatLevel>1000 );

	int oldMaxHitPoints = max_hit_points();

	skill.set_combat_level(combatLevel);		// it will affect max_hit_points()

	hit_points = hit_points * max_hit_points() / oldMaxHitPoints;
	hit_points = min(hit_points, max_hit_points());

	// --------- update can_guard_flag -------//

	// ##### begin Gilbert 4/11 #######//
	if( combat_level() >= unit_res[unit_id]->guard_combat_level)
	// ##### end Gilbert 4/11 #######//
	{
		can_guard_flag = sprite_info->can_guard_flag;
	}
	else
	{
		can_guard_flag = 0;
	}

	if( combat_level() <= MAX_COMBAT_TRAIN )
		max_power = combat_level() + 50;
	else
		max_power = combat_level() / 10 + ( MAX_COMBAT_TRAIN + 50 - MAX_COMBAT_TRAIN / 10 );

	// ###### patch begin Gilbert 17/2 #####//
//	if( race_id == RACE_VIKING && nation_recno 
//		&& god_res[GOD_VIKING]->nation_prayer_count(nation_recno) > 0 )
	if( nation_recno && god_res[GOD_VIKING]->nation_prayer_count(nation_recno) > 0 )
	{
		// max_power += 20;
		max_power += 25;
	}
	// ###### patch end Gilbert 17/2 #####//

	cur_power = min(cur_power, max_power);
}
Пример #3
0
//--------- Begin of function Unit::unit_name ---------//
//
// [int] withTitle - whether return a string with the title of the unit
//                   or not. (default: 1)
//
// [int] firstNameOnly - whether return the first word of the name only
//							(default: 0)
//
const char* Unit::unit_name(int withTitle, int firstNameOnly)
{
//	static String str;

	UnitInfo* unitInfo = unit_res[unit_id];

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

	if( race_id && unit_id != UNIT_WAGON )
	{
		const char *baseName;
		if( hero_id )
			baseName = hero_res[hero_id]->name;
		else if( rank_id == RANK_KING )		// use the player name
			baseName = nation_array[nation_recno]->king_name(firstNameOnly);
		else
			baseName = race_res[race_id]->get_name(name_id, firstNameOnly?1:0);

		if( withTitle )
		{
			if( unit_mode == UNIT_MODE_REBEL )
			{
				if( rank_id == RANK_GENERAL )
					return text_unit.str_rebel_unit_titled( race_id, baseName, rank_id );
			}
			else
			{
				if( rank_id != RANK_SOLDIER )	// human soldier has no "SOLIDER" has title
					return text_unit.str_unit_titled( race_id, baseName, rank_id );
			}
		}

		return baseName;
	}
	else
	{
		int kingAnimal = 0;
		if (unitInfo->unit_class == UNIT_CLASS_ANIMAL && attack_count > 1)
		{
			AttackInfo *attackInfo = attack_info_array + 1;
			if (combat_level() >= attackInfo->combat_level)
				kingAnimal = 1;
		}

		return text_unit.str_non_race_unit_name( unitInfo->name,
			(unitInfo->class_info.has_weapon_version ? get_weapon_version() : 0),
			(unitInfo->unit_class != UNIT_CLASS_GOD ? name_id : 0),		// don't put serial no. to god
			kingAnimal );
   }

//   return str;
}
Пример #4
0
int Unit::think_use_special_ability()
{
	int spLevel = 0;

	if( is_human() )
	{
		if( combat_level() > MAX_COMBAT_BATTLE )
			spLevel = combat_level() / 4;
		else if( skill.max_combat_level > MAX_COMBAT_BATTLE )		// potential hero can trigger special power
			spLevel = 1;
		else
			return 0;

		if( info.game_date - last_special_ability_start_date < SPECIAL_ABILITY_DELAY )
			return 0;

		if( m.random(100+spLevel) < 100 )
			return 0;

		use_special_ability();
		return is_special_ability_effective();
	}
	return 0;
}
Пример #5
0
//-------- Begin of function Trainee::advanced_train ------//
//
// Non-basic training: train the unit if it has potential.
//
void Trainee::advanced_train(int firmRecno)
{
	int nationRecno = firm_array[firmRecno]->nation_recno;

	//------ train spy skill --------//

	if( train_spy_potential && spy_skill < MAX_SKILL_TRAIN )
	{
		int incValue = (MAX_SKILL_TRAIN - (int)spy_skill)
			* train_spy_potential / 100;

		incValue = MAX(20,incValue);

		spy_skill += (float) incValue / 100;

		if( spy_skill > MAX_SKILL_TRAIN )
			spy_skill = MAX_SKILL_TRAIN;
	}

	//------ train combat --------//

	if( train_combat_potential && combat_level() < MAX_COMBAT_TRAIN )
	{
		int incValue = (MAX_COMBAT_TRAIN - (int)combat_level() )
			* train_combat_potential / 100;

		incValue = MAX(20,incValue);

		// ###### patch begin Gilbert 16/2 #######//
		// ------ effect of god ----------//

		//if( race_id == RACE_CELTIC && nationRecno 
		//	&& god_res[GOD_CELTIC]->nation_prayer_count(nationRecno) > 0 )
		if( nationRecno && god_res[GOD_CELTIC]->nation_prayer_count(nationRecno) > 0 )
		{
			if( race_id == RACE_CELTIC )
				incValue += incValue / 2;		// 50% skill increase in fort
			else
				incValue += incValue / 5;		// 20% skill increase in fort
		}
		// ###### patch end Gilbert 16/2 #######//

		// ###### patch begin Gilbert 23/12 #########//
		// penalty of egyptain
		if( race_id == RACE_EGYPTIAN && nationRecno
			&& god_res[GOD_EGYPTIAN]->nation_prayer_count(nationRecno) > 0 )
		{
			incValue = incValue * (MAX_WORKER*2) / (MAX_WORKER*2+god_res[GOD_EGYPTIAN]->nation_prayer_count(nationRecno));
		}
		// ###### patch end Gilbert 23/12 #########//

		skill.inc_combat_level( (float)incValue/100 );
	}

	//------ train leadership --------//

	if( train_skill_potential && skill_level() < MAX_SKILL_TRAIN )
	{
		int incValue = (MAX_SKILL_TRAIN - (int)skill_level() )
			* train_skill_potential / 100;

		skill.inc_skill_level( (float)incValue/100 );
	}
}
Пример #6
0
//--------- Begin of function Unit::think_independent_hero --------//
//
void Unit::think_independent_hero()
{
	//------ think about go to serve a kingdom -------//

	int bestNationRecno=0, curRating;

	int bestRating = (skill_level() + combat_level()/2) / 3;

	if( item.id )
		bestRating += (item_res.rareness(item.id)+1) * 10;

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

	int i;
	for( i=nation_array.size() ; i>0 ; i-- )
	{
		if( nation_array.is_deleted(i) )
			continue;

		Nation* nationPtr = nation_array[i];

		curRating = (int) nationPtr->reputation + nationPtr->overall_rating;

		if( sprite_recno%2==0 )			// some heroes look at kill_monster_score, but some don't
			curRating += (int) nationPtr->kill_monster_score/10;

		if( race_id == nationPtr->race_id )
			curRating += 10;

		if( curRating > bestRating )
		{
			bestRating = curRating;
			bestNationRecno = i;
		}
	}

	if( bestNationRecno )
	{
		//------ change nation now --------//

		if( !betray(bestNationRecno) )
			return;

		//---- the unit moves close to the newly joined nation ----//

		ai_move_to_nearby_town();
		return;
	}

	//---- randomly locate a destination to walk to ----//

	int xLoc, yLoc, regionId = region_id();

	for( i=100 ; i>0 ; i-- )
	{
		xLoc = m.random(MAX_WORLD_X_LOC);
		yLoc = m.random(MAX_WORLD_Y_LOC);

		Location* locPtr = world.get_loc(xLoc, yLoc);

		if( locPtr->walkable() && locPtr->region_id == regionId )
			break;
	}

	if( i==0 )
		return;

	move(xLoc, yLoc);
}
Пример #7
0
//--------- Begin of function Unit::next_day ---------//
//
void Unit::next_day()
{
	int unitRecno = sprite_recno;

   err_when( unit_array.is_deleted(unitRecno) );

	err_when( race_id && !is_visible() && unit_mode==0 );

	err_when( team_info && !mem.get_mem_size(team_info) );

	// ##### begin Gilbert 2/3 #####//
	err_when( race_id && unit_id != UNIT_WAGON && !name_id );
	// ##### end Gilbert 2/3 #####//

	//------- functions for non-independent nations only ------//

   if( nation_recno )
   {
      pay_expense();

		if( unit_array.is_deleted(unitRecno) )		// if its hit points go down to 0, is_deleted() will return 1.
			return;

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

		if( info.game_date%30 == sprite_recno%30 )
		{
			update_loyalty();
		   err_when( unit_array.is_deleted(unitRecno) );
		}

		//------- think about rebeling -------------//

		if( info.game_date%15 == sprite_recno%15 )
		{
			if( think_betray() )
				return;
		}
	}

	//------- recover from damage -------//

	if( info.game_date%4 == sprite_recno%4 )   // recover points per 4 days 
	{
		process_recover();
		err_when( unit_array.is_deleted(unitRecno) );
	}

   //------- restore cur_power --------//

	cur_power += 5;

	if( cur_power > max_power)
		cur_power = max_power;

	// ------ process magic effect ---------//

	if( invulnerable_day_count > 0 )
		--invulnerable_day_count;

   //------- king undie flag (for testing games only) --------//

   if( config.king_undie_flag && rank_id == RANK_KING &&
       nation_recno && !nation_array[nation_recno]->is_ai() )
   {
		hit_points = (float) max_hit_points();
		// ####### begin Gilbert 27/1 ######//
		if( invulnerable_day_count == 0 )
			++invulnerable_day_count;
		// ####### end Gilbert 27/1 ######//
	}

	//-------- if aggresive_mode is 1 --------//

	if( is_visible() )
		think_aggressive_action();

	// --------- process item -------//
	
	item.next_day();

	//---------- debug ------------//

#ifdef DEBUG
   err_when( race_id &&
		unit_res[unit_id]->unit_class != UNIT_CLASS_HUMAN && 
		unit_res[unit_id]->unit_class != UNIT_CLASS_MONSTER && 
		unit_res[unit_id]->unit_class != UNIT_CLASS_WAGON );

	if( unit_mode == UNIT_MODE_CONSTRUCT_TOWN )
		err_when( town_array[unit_mode_para]->builder_recno != sprite_recno );

	err_when( unit_mode==UNIT_MODE_REBEL && nation_recno );		// rebels must be independent

	//------ debug: spy ----------//

	if( spy_recno )
	{
		err_when( spy_array.is_deleted(spy_recno) );

		Spy* spyPtr = spy_array[spy_recno];

		err_when( nation_recno != spyPtr->cloaked_nation_recno );

		if( unit_mode == UNIT_MODE_OVERSEE )
		{
			err_when( spyPtr->spy_place != SPY_FIRM );
			err_when( spyPtr->spy_place_para != unit_mode_para );
		}
		else
		{
			err_when( spyPtr->spy_place != SPY_MOBILE );
			err_when( spyPtr->spy_place_para != sprite_recno );
		}

		// ####### begin Gilbert 24/2 ########//
		err_when( unique_id != spyPtr->unique_id );
		// ####### end Gilbert 24/2 ########//
	}

	//------ debug: team ----------//

	if( leader_unit_recno )
	{
      Unit* unitPtr = unit_array[leader_unit_recno];

		err_when( unitPtr->rank_id != RANK_GENERAL && unitPtr->rank_id != RANK_KING );
	}

	err_when( (rank_id == RANK_GENERAL || rank_id == RANK_KING) &&
				 !team_info );

	if( team_info )
	{
		for( int i=0 ; i<team_info->member_count ; i++ )
		{
			Unit* unitPtr = unit_array[team_info->member_unit_array[i]];

			if( unitPtr->sprite_recno == sprite_recno )		// the same unit
				continue;

			err_when( unitPtr->leader_unit_recno != sprite_recno );
		}
	}

	if( leader_unit_recno && unit_mode != UNIT_MODE_REBEL )		// in rebel mode, the leader_unit_recno is not linked to team_info
	{
		Unit* leaderUnit = unit_array[leader_unit_recno];

		err_when( !leaderUnit->team_info );

		for( int i=0 ; i<leaderUnit->team_info->member_count ; i++ )
		{
			if( leaderUnit->team_info->member_unit_array[i] == sprite_recno )
				break;
		}

		err_when( i==leaderUnit->team_info->member_count );		// not found

		err_when( unit_array.is_truly_deleted(leader_unit_recno) );
		err_when( unit_array[leader_unit_recno]->nation_recno != nation_recno );
//		err_when( unit_array[leader_unit_recno]->team_id != team_id );
	}

	//------ debug: AI action ----------//

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

		for( int actionRecno=nationPtr->action_count() ; actionRecno>0 ; actionRecno-- )
		{
			if( nationPtr->is_action_deleted(actionRecno) )
				continue;

			ActionNode* actionNode = nationPtr->get_action(actionRecno);

			if( cur_order.ai_action_id == actionNode->action_id )
			{
				err_when( actionNode->processing_instance_count<1 );
				break;
			}
		}
	}

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

	err_when( hit_points > max_hit_points() );
	err_when( max_hit_points() == 0 );

   err_when( combat_level()<0 );
	err_when( combat_level()>1000 );

	err_when( unit_mode==UNIT_MODE_REBEL && spy_recno );			// no rebel spies
	err_when( unit_mode==UNIT_MODE_REBEL && nation_recno );		// all rebels must be independent units

	err_when( unit_mode==UNIT_MODE_TOWN_DEFENDER && spy_recno );			// no rebel spies

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

	err_when( nation_contribution < 0 );
	err_when( nation_contribution > MAX_NATION_CONTRIBUTION );

	err_when( is_ai && ( !nation_recno || !nation_array[nation_recno]->is_ai() ) );

#else		// fix bug on fly in the release version

	// ######## begin Gilbert 5/2 #####//
//	if( combat_level() > skill.max_combat_level )
//		combat_level() = skill.max_combat_level;
	if( skill.actual_combat_level(NULL) > skill.max_combat_level )		// raw combat level
		set_combat_level( skill.max_combat_level );
	// ######## end Gilbert 5/2 #####//

#endif
}
Пример #8
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 );
}
Пример #9
0
//--------- Begin of function InnUnit::set_hire_cost ---------//
//
void InnUnit::set_hire_cost()
{
	hire_cost = hero_res.hire_cost( combat_level(), skill.max_combat_level,
					skill_level(), spy_skill, &item );
}