//-------- 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; }
//--------- 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); }
//--------- 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; }
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; }
//-------- 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 ); } }
//--------- 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); }
//--------- 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 }
//--------- 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 ); }
//--------- 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 ); }