// --------- Begin of function Unit::teleport --------// // return 1 on success int Unit::teleport(int targetXLoc, int targetYLoc ) { // ###### begin Gilbert 21/3 ########// if( !is_visible() ) return 0; // ###### end Gilbert 21/3 ########// if( world.check_unit_space( targetXLoc, targetYLoc, targetXLoc+loc_width-1, targetYLoc+loc_height-1, mobile_type) ) { stop_order(); int dx, dy; for( dy = 0; dy < loc_width; ++dy ) for( dx = 0; dx < loc_height; ++dx ) world.get_loc(next_x_loc()+dx, next_y_loc()+dy)->remove_unit( mobile_type ); cur_x = go_x = next_x = targetXLoc * LOCATE_WIDTH; cur_y = go_y = next_y = targetYLoc * LOCATE_HEIGHT; for( dy = 0; dy < loc_width; ++dy ) for( dx = 0; dx < loc_height; ++dx ) world.get_loc( next_x_loc()+dx, next_y_loc()+dy)->set_unit( sprite_recno, mobile_type ); explore_area(); return 1; } return 0; }
//--------- Begin of function Unit::resign ---------// // // Resign the unit. // void Unit::resign(int remoteAction) { if( !remoteAction && remote.is_enable() ) { // packet structure : <unit recno> <nation recno> short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_RESIGN, 2*sizeof(short)); *shortPtr = sprite_recno; shortPtr[1] = nation_array.player_recno; return; } //---- increase the wandering count when a unit is disbanded ----// if( is_human() ) town_array.race_wander_pop_array[race_id-1] += 2; // disbanding one resulted in two wandering units to make the effect more significant //--- if the unit is visible, stop the current order ----// if( is_visible() ) stop_order(); //--- if the spy is resigned by an enemy, display a message ---// if( spy_recno && true_nation_recno() != nation_recno ) // the spy is cloaked in an enemy nation when it is resigned { //------ decrease reputation ------// nation_array[true_nation_recno()]->change_reputation((float)-SPY_KILLED_REPUTATION_DECREASE); //------- add news message -------// // #### begin Gilbert 24/12 ######// // if( nation_recno == nation_array.player_recno ) // display when the player has revealed an enemy spy // info.spy_execute = 1; // #### end Gilbert 24/12 ######// if( true_nation_recno() == nation_array.player_recno || // display when the player's spy is revealed or the player has revealed an enemy spy nation_recno == nation_array.player_recno ) { //--- If a spy is caught, the spy's nation's reputation wil decrease ---// news_array.spy_killed(spy_recno); } } //----------------------------------------------// if( rank_id == RANK_GENERAL ) // if this is a general, news_array.general_die() will be called, set news_add_flag to 0 to suppress the display of thew news news_array.news_add_flag=0; unit_array.del( sprite_recno ); news_array.news_add_flag=1; }
//--------- Begin of function Unit::ai_handle_seek_path_fail --------// // // This function is used for handling cases when AI units are not // able to seek a path successfully. // int Unit::ai_handle_seek_path_fail() { if( seek_path_fail_count < 5*SEEK_PATH_FAIL_INCREMENT ) // wait unit it has failed many times return 0; //----- try to move to a new location -----// if( seek_path_fail_count==5*SEEK_PATH_FAIL_INCREMENT ) { stop_order(); // stop the unit and think for new action return 0; } //--- if the seek path has failed too many times, resign the unit ---// int resignFlag = 0; if( rank_id == RANK_SOLDIER && !leader_unit_recno ) { if( seek_path_fail_count>=7*SEEK_PATH_FAIL_INCREMENT ) resignFlag = 1; } else if( rank_id == RANK_GENERAL ) { if( seek_path_fail_count >= (7+skill_level()/10)*SEEK_PATH_FAIL_INCREMENT ) resignFlag = 1; } else { if( seek_path_fail_count >= 7*SEEK_PATH_FAIL_INCREMENT ) resignFlag = 1; } if( resignFlag && is_visible() ) { resign(COMMAND_AI); return 1; } else return 0; }
//------------- Begin of function Unit::set_die --------------// // // set parameters for unit die // void Unit::set_die() { if( cur_action == SPRITE_DIE ) return; stop_order(); err_when(hit_points>0); cur_action = SPRITE_DIE; cur_frame = 1; //---- if this unit is led by a leader, only mobile units has leader_unit_recno assigned to a leader -----// // ###### patch begin Gilbert 3/9 #######// if( leader_unit_recno ) { // the leader unit may have been killed at the same time if( !unit_array.is_deleted(leader_unit_recno) ) { if( unit_array[leader_unit_recno]->team_info ) { unit_array[leader_unit_recno]->team_info->del_member(sprite_recno); } else { err_here(); int b = 0; // set break point here } } leader_unit_recno = 0; } // if( team_info ) // { // team_info->reset(); // } // ###### patch end Gilbert 3/9 #######// }
//--------- Begin of function Unit::change_nation ---------// // // This function is called when a unit change nation. // It is not necessarily a result of betray, when a spy // hands over his new nation to his parent nation, this // function will also be called. // // <int> newNationRecno - change the nation of the unit. // void Unit::change_nation(int newNationRecno) { err_when( newNationRecno && nation_array.is_deleted(newNationRecno) ); err_when( unit_mode == UNIT_MODE_REBEL ); // rebels do not change nation //--- 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; } //---------------------------------// int oldAiUnit = is_ai; int oldNationRecno = nation_recno; //-- if the player is giving a command to this unit, cancel the command --// if( nation_recno == nation_array.player_recno && sprite_recno == unit_array.selected_recno && power.command_id ) { power.command_id = 0; } //---------- stop all action to attack this unit ------------// unit_array.stop_attack_obj(base_obj_recno); //---- update nation_unit_count_array[] ----// unit_res[unit_id]->unit_change_nation(newNationRecno, nation_recno, rank_id); //------- if the nation has an AI action -------// stop_order(); // clear the existing order //---------------- update vars ----------------// // unit_group_id = unit_array.cur_group_id++; // separate from the current group nation_recno = newNationRecno; home_camp_firm_recno = 0; // reset it if( race_id ) { nation_contribution = 0; // contribution to the nation total_reward = 0; } // #### begin Gilbert 24/12 #######// // -------- reset royal -------// is_royal = 0; // #### end Gilbert 24/12 #######// //-------- if change to one of the existing nations ------// is_ai = nation_recno && nation_array[nation_recno]->is_ai(); //------------ update AI info --------------// if( oldNationRecno ) { Nation* nationPtr = nation_array[oldNationRecno]; if( rank_id == RANK_GENERAL || rank_id == RANK_KING ) nationPtr->del_general_info(sprite_recno); else if( unit_res[unit_id]->unit_class == UNIT_CLASS_CARAVAN ) nationPtr->del_caravan_info(sprite_recno); else if( unit_res[unit_id]->unit_class == UNIT_CLASS_SHIP ) nationPtr->del_ship_info(sprite_recno); } if( nation_recno ) { Nation* nationPtr = nation_array[nation_recno]; if( rank_id == RANK_GENERAL || rank_id == RANK_KING ) nationPtr->add_general_info(sprite_recno); else if( unit_res[unit_id]->unit_class == UNIT_CLASS_CARAVAN ) nationPtr->add_caravan_info(sprite_recno); else if( unit_res[unit_id]->unit_class == UNIT_CLASS_SHIP ) nationPtr->add_ship_info(sprite_recno); } //------ if this unit oversees a firm -----// if( unit_mode==UNIT_MODE_OVERSEE ) firm_array[unit_mode_para]->change_nation(newNationRecno); //----- this unit was defending the town before it gets killed ----// else if( unit_mode==UNIT_MODE_TOWN_DEFENDER ) { if( !town_array.is_deleted(unit_mode_para) ) town_array[unit_mode_para]->reduce_defender_count(); set_mode(0); // reset unit mode } //---- if the unit is no longer the same nation as the leader ----// if( leader_unit_recno ) { Unit* leaderUnit = unit_array[leader_unit_recno]; if( leaderUnit->nation_recno != nation_recno ) { err_when( !leaderUnit->team_info ); leaderUnit->team_info->del_member(sprite_recno); leader_unit_recno = 0; // team_id = 0; } } // ##### begin Gilbert 9/2 #######// explore_area(); // ##### end Gilbert 9/2 #######// //------ if it is currently selected -------// if( selected_flag ) info.disp(); err_when( spy_recno && spy_array[spy_recno]->cloaked_nation_recno != nation_recno ); if( spy_recno && spy_array[spy_recno]->cloaked_nation_recno != nation_recno ) // BUGHERE - fix bug on-fly spy_array[spy_recno]->cloaked_nation_recno = nation_recno; }
//--------- 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(); } } } }
int Unit::think_stop_chase() { //-----------------------------------------------------// // // Stop the chase if the target is being far away from // its original attacking location. // //-----------------------------------------------------// if( !(cur_order.mode==UNIT_ATTACK && ai_original_target_x_loc>=0) ) return 0; if( base_obj_array.is_deleted(cur_order.para) ) { stop_order(); return 1; } Unit* targetUnit = base_obj_array[cur_order.para]->cast_to_Unit(); if( !targetUnit ) // this function only deal with chasing enemy units return 0; if( !targetUnit->is_visible() ) { stop_order(); return 1; } //----------------------------------------// int aiChaseDistance = 10 + nation_array[nation_recno]->pref_military_courage/20; // chase distance: 10 to 15 int curDistance = misc.points_distance( targetUnit->next_x_loc(), targetUnit->next_y_loc(), ai_original_target_x_loc, ai_original_target_y_loc ); if( curDistance <= aiChaseDistance ) return 0; //--------- stop the unit ----------------// stop_order(); //--- if this unit leads a troop, stop the action of all troop members as well ---// int leaderUnitRecno; if( leader_unit_recno ) leaderUnitRecno = leader_unit_recno; else leaderUnitRecno = sprite_recno; TeamInfo* teamInfo = unit_array[leaderUnitRecno]->team_info; if( teamInfo ) { for( int i=teamInfo->member_count-1 ; i>=0 ; i-- ) { int unitRecno = teamInfo->member_unit_array[i]; if( unit_array.is_deleted(unitRecno) ) continue; unit_array[unitRecno]->stop_order(); } } return 1; }