/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OUNITD.CPP //Description : Object Unit defense functions //Owner : Alex #include #include #include #include #include #include #include #include #ifdef NO_DEBUG_UNIT #undef err_when #undef err_here #undef err_if #undef err_else #undef err_now #define err_when(cond) #define err_here() #define err_if(cond) #define err_else #define err_now(msg) #undef DEBUG #endif //=================================================================================================// // Unit's defend mode generalized functions //=================================================================================================// //--------- Begin of function Unit::in_any_defense_mode ---------// // check whether the unit is in defense mode // // return 1 if it is // return 0 otherwise // int Unit::in_any_defense_mode() { return (action_mode2>=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2<=ACTION_MONSTER_DEFEND_BACK_FIRM); } //----------- End of function Unit::in_any_defense_mode -----------// //--------- Begin of function Unit::general_defend_mode_detect_target ---------// // call the appropriate defend function for the current type of defend // // checkDefendMode - flag to check defend mode or not // void Unit::general_defend_mode_detect_target(int checkDefendMode) { stop(); switch(action_mode2) { case ACTION_AUTO_DEFENSE_ATTACK_TARGET: defense_detect_target(); break; case ACTION_DEFEND_TOWN_ATTACK_TARGET: defend_town_detect_target(); break; case ACTION_MONSTER_DEFEND_ATTACK_TARGET: monster_defend_detect_target(); break; default: if(checkDefendMode) err_here(); break; } } //----------- End of function Unit::general_defend_mode_detect_target -----------// //--------- Begin of function Unit::general_defend_mode_process_attack_target ---------// // process unit defense action. If target is dead, action_mode changes to detect_mode // // return 1 if action mode changes to detect mode // return 0 otherwise // int Unit::general_defend_mode_process_attack_target() { Location *locPtr; Unit *unitPtr; Town *townPtr; Firm *firmPtr; SpriteInfo *spriteInfo; FirmInfo *firmInfo; int clearToDetect = 0; //------------------------------------------------------------------------------// // if the unit's action mode is in defensive attack action, process the corresponding // checking. //------------------------------------------------------------------------------// switch(action_mode) { case ACTION_ATTACK_UNIT: if(unit_array.is_deleted(action_para2)) clearToDetect++; else { err_when(unit_array.is_deleted(action_para2)); unitPtr = unit_array[action_para2]; //if(unitPtr->cur_action==SPRITE_IDLE) // clearToDetect++; if(!nation_can_attack(unitPtr->nation_recno)) // cannot attack this nation clearToDetect++; } break; case ACTION_ATTACK_FIRM: if(firm_array.is_deleted(action_para2)) clearToDetect++; else { err_when(firm_array.is_deleted(action_para2)); firmPtr = firm_array[action_para2]; if(!nation_can_attack(firmPtr->nation_recno)) // cannot attack this nation clearToDetect++; } break; case ACTION_ATTACK_TOWN: if(town_array.is_deleted(action_para2)) clearToDetect++; else { err_when(town_array.is_deleted(action_para2)); townPtr = town_array[action_para2]; if(!nation_can_attack(townPtr->nation_recno)) // cannot attack this nation clearToDetect++; } break; case ACTION_ATTACK_WALL: locPtr = world.get_loc(action_x_loc2, action_y_loc2); if(!locPtr->is_wall() || !nation_can_attack(locPtr->power_nation_recno)) clearToDetect++; break; default: clearToDetect++; break; } //------------------------------------------------------------------------------// // suitation changed to defensive detecting mode //------------------------------------------------------------------------------// if(clearToDetect) { //----------------------------------------------------------// // target is dead, change to detect state for another target //----------------------------------------------------------// reset_action_para(); return 1; } else if(waiting_termsprite_info; //-----------------------------------------------------------------// // attack the target if able to reach the target surrounding, otherwise // continue to wait //-----------------------------------------------------------------// action_x_loc2 = unitPtr->next_x_loc(); // update target location action_y_loc2 = unitPtr->next_y_loc(); if(space_for_attack(action_x_loc2, action_y_loc2, unitPtr->mobile_type, spriteInfo->loc_width, spriteInfo->loc_height)) attack_unit(unitPtr->sprite_recno); break; case ACTION_ATTACK_FIRM: err_when(firm_array.is_deleted(action_para2) || !firmPtr); firmInfo = firm_res[firmPtr->firm_id]; //-----------------------------------------------------------------// // attack the target if able to reach the target surrounding, otherwise // continue to wait //-----------------------------------------------------------------// attack_firm(action_x_loc2, action_y_loc2); if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2, firmInfo->loc_width, firmInfo->loc_height)) waiting_term = 0; break; case ACTION_ATTACK_TOWN: err_when(town_array.is_deleted(action_para2) || !townPtr); //-----------------------------------------------------------------// // attack the target if able to reach the target surrounding, otherwise // continue to wait //-----------------------------------------------------------------// attack_town(action_x_loc2, action_y_loc2); if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT)) waiting_term = 0; break; case ACTION_ATTACK_WALL: err_when(action_para || action_para2); attack_wall(action_x_loc2, action_y_loc2); if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2, 1, 1)) waiting_term = 0; break; default: err_here(); break; } } return 0; } //----------- End of function Unit::general_defend_mode_process_attack_target -----------// //=================================================================================================// // Unit's defense mode //=================================================================================================// //--------- Begin of function Unit::defense_attack_unit ---------// // defensive attack units // // targetRecno - recno of the target // void Unit::defense_attack_unit(short targetRecno) { action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET; attack_unit(targetRecno); } //----------- End of function Unit::defense_attack_unit -----------// //--------- Begin of function Unit::defense_attack_firm ---------// // defensive attack firm // // targetXLoc - x location of the firm // targetYLoc - y location of the firm // void Unit::defense_attack_firm(int targetXLoc, int targetYLoc) { action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET; attack_firm(targetXLoc, targetYLoc); } //----------- End of function Unit::defense_attack_firm -----------// //--------- Begin of function Unit::defense_attack_town ---------// // defensive attack town // // targetXLoc - x location of the town // targetYLoc - y location of the town // void Unit::defense_attack_town(int targetXLoc, int targetYLoc) { action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET; attack_town(targetXLoc, targetYLoc); } //----------- End of function Unit::defense_attack_town -----------// //--------- Begin of function Unit::defense_attack_wall ---------// // defensive attack wall // // targetXLoc - x location of wall // targetYLoc - y location of wall // void Unit::defense_attack_wall(int targetXLoc, int targetYLoc) { action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET; attack_wall(targetXLoc, targetYLoc); } //----------- End of function Unit::defense_attack_wall -----------// //--------- Begin of function Unit::defense_detect_target ---------// // set parameters for unit's defensive mode // void Unit::defense_detect_target() { action_mode2 = ACTION_AUTO_DEFENSE_DETECT_TARGET; action_para2 = AUTO_DEFENSE_DETECT_COUNT; action_x_loc2 = -1; action_y_loc2 = -1; } //----------- End of function Unit::defense_detect_target -----------// //--------- Begin of function Unit::defense_back_camp ---------// // set parameters for unit's to return camp // // firmXLoc - x location of the firm // firmYLoc - y location of the firm // void Unit::defense_back_camp(int firmXLoc, int firmYLoc) { err_when(firm_array[world.get_loc(firmXLoc, firmYLoc)->firm_recno()]->firm_id!=FIRM_CAMP); err_when(firm_array[world.get_loc(firmXLoc, firmYLoc)->firm_recno()]->firm_recno!=action_misc_para); assign(firmXLoc, firmYLoc); action_mode2 = ACTION_AUTO_DEFENSE_BACK_CAMP; } //----------- End of function Unit::defense_back_camp -----------// //--------- Begin of function Unit::process_auto_defense_attack_target ---------// // process the action for unit's defensive attack // void Unit::process_auto_defense_attack_target() { err_when(action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET); if(general_defend_mode_process_attack_target()) { defense_detect_target(); err_when(action_mode!=ACTION_STOP || action_para || action_x_loc!=-1 || action_y_loc!=-1 || cur_action==SPRITE_ATTACK); } } //----------- End of function Unit::process_auto_defense_attack_target -----------// //--------- Begin of function Unit::process_auto_defense_detect_target ---------// // process action for unit's defensive detecet target // void Unit::process_auto_defense_detect_target() { err_when(action_mode2!=ACTION_AUTO_DEFENSE_DETECT_TARGET); err_when(action_mode!=ACTION_STOP); err_when(action_para!=0); err_when(action_x_loc!=-1 || action_y_loc!=-1 || action_x_loc!=-1 || action_y_loc2!=-1); //----------------------------------------------------------------// // no target or target is out of detect range, so change state to // back camp //----------------------------------------------------------------// if(!action_para2) { err_when(action_misc!=ACTION_MISC_DEFENSE_CAMP_RECNO || !action_misc_para); int back = 0; FirmCamp *campPtr; Unit *targetPtr; if(firm_array.is_deleted(action_misc_para)) back++; else { campPtr = (FirmCamp*) firm_array[action_misc_para]; if(unit_array.is_deleted(campPtr->defend_target_recno)) back++; else { targetPtr = unit_array[campPtr->defend_target_recno]; if(targetPtr->action_mode!=ACTION_ATTACK_FIRM || targetPtr->action_para!=campPtr->firm_recno) back++; } } if(!back) { //action_mode2 = ACTION_AUTO_DEFENSE_DETECT_TARGET; action_para2 = AUTO_DEFENSE_DETECT_COUNT; return; } process_auto_defense_back_camp(); return; } //----------------------------------------------------------------// // defense_detecting target algorithm //----------------------------------------------------------------// int startLoc; int dimension; switch(action_para2%GAME_FRAMES_PER_DAY) { case 3: startLoc = 2;// 1-7, check 224 = 15^2-1 //### begin alex 3/10 ###// dimension = 7; //#### end alex 3/10 ####// break; case 2: startLoc = 122;// 6-8, check 168 = 17^2-11^2 dimension = 8; break; case 1: startLoc = 170;// 7-9, check 192 = 19^2-13^2 dimension = EFFECTIVE_AUTO_DEFENSE_DISTANCE; break; default: action_para2--; return; } //---------------------------------------------------------------// // attack the target if target detected, or change the detect region //---------------------------------------------------------------// if(!idle_detect_attack(startLoc, dimension, 1)) // defense mode is on action_para2--; } //----------- End of function Unit::process_auto_defense_detect_target -----------// //--------- Begin of function Unit::process_auto_defense_back_camp ---------// // process action for the units to return camp // void Unit::process_auto_defense_back_camp() { int clearDefenseMode = 0; if(action_mode!=ACTION_ASSIGN_TO_FIRM) // the unit may become idle or unable to reach firm, reactivate it { Firm *firmPtr; if(action_misc!=ACTION_MISC_DEFENSE_CAMP_RECNO || !action_misc_para || firm_array.is_deleted(action_misc_para)) clearDefenseMode++; else { firmPtr = firm_array[action_misc_para]; if(firmPtr->firm_id!=FIRM_CAMP || firmPtr->nation_recno!=nation_recno) clearDefenseMode++; else { defense_back_camp(firmPtr->loc_x1, firmPtr->loc_y1); // go back to the military camp err_when(action_mode2!=ACTION_AUTO_DEFENSE_BACK_CAMP); return; } } } else if(cur_action==SPRITE_IDLE) { if(firm_array.is_deleted(action_misc_para)) clearDefenseMode++; else { Firm *firmPtr = firm_array[action_misc_para]; defense_back_camp(firmPtr->loc_x1, firmPtr->loc_y1); err_when(action_mode2!=ACTION_AUTO_DEFENSE_BACK_CAMP); return; } } err_when(!clearDefenseMode); //----------------------------------------------------------------// // clear order if the camp is deleted //----------------------------------------------------------------// stop2(); reset_action_misc_para(); err_when(in_auto_defense_mode()); } //----------- End of function Unit::process_auto_defense_back_camp -----------// //------------- Begin of function Unit::in_auto_defense_mode --------------// // check whether the units in auto defense mode // int Unit::in_auto_defense_mode() { return (action_mode2>=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2<=ACTION_AUTO_DEFENSE_BACK_CAMP); } //----------- End of function Unit::in_auto_defense_mode -----------// //------------- Begin of function Unit::defense_follow_target --------------// // decide whether to follow the target // // return 0 if aborting attack the current target and go back to military camp // return 1 otherwise // int Unit::defense_follow_target() { #define PROB_HOSTILE_RETURN 10 #define PROB_FRIENDLY_RETURN 20 #define PROB_NEUTRAL_RETURN 30 if(unit_array.is_deleted(action_para)) return 1; if(cur_action==SPRITE_ATTACK) return 1; Unit *targetPtr = unit_array[action_para]; Location *locPtr = world.get_loc(action_x_loc, action_y_loc); if(!locPtr->has_unit(targetPtr->mobile_type)) return 1; // the target may be dead or invisible int returnFactor, abortAction = 0; //-----------------------------------------------------------------// // calculate the chance to go back to military camp in following the // target //-----------------------------------------------------------------// if(locPtr->power_nation_recno==nation_recno) return 1; // target within our nation else if(!locPtr->power_nation_recno) // is neutral returnFactor = PROB_NEUTRAL_RETURN; else { Nation *locNationPtr = nation_array[locPtr->power_nation_recno]; if(locNationPtr->get_relation_status(nation_recno)==NATION_HOSTILE) returnFactor = PROB_HOSTILE_RETURN; else returnFactor = PROB_FRIENDLY_RETURN; } if(!abortAction) { SpriteInfo *targetSpriteInfo = targetPtr->sprite_info; //-----------------------------------------------------------------// // if the target moves faster than this unit, it is more likely for // this unit to go back to military camp. //-----------------------------------------------------------------// //-**** should also consider the combat level and hit_points of both unit ****-// if(targetSpriteInfo->speed > sprite_info->speed) returnFactor -= 5; if(m.random(returnFactor)==0) // return to camp if true abortAction++; else return 1; } err_when(!abortAction); err_when(action_mode==ACTION_ASSIGN_TO_FIRM); // if so, process_auto_defense_back_camp() cannot process successfully process_auto_defense_back_camp(); return 0; // cancel attack } //----------- End of function Unit::defense_follow_target -----------// //------------- Begin of function Unit::clear_unit_defense_mode --------------// // clear defensive mode // void Unit::clear_unit_defense_mode() { //------- cancel defense mode and continue the current action -------// action_mode2 = action_mode; action_para2 = action_para; action_x_loc2 = action_x_loc; action_y_loc2 = action_y_loc; reset_action_misc_para(); if( unit_mode == UNIT_MODE_DEFEND_TOWN ) set_mode(0); // reset unit mode } //----------------- End of function Unit::clear_unit_defense_mode ----------------// //=================================================================================================// // Town unit's defend mode, eg rebel //=================================================================================================// //--------- Begin of function Unit::defend_town_attack_unit ---------// // set to defensive mode // // targetRecno - record of target // void Unit::defend_town_attack_unit(short targetRecno) { action_mode2 = ACTION_DEFEND_TOWN_ATTACK_TARGET; attack_unit(targetRecno); } //----------- End of function Unit::defend_town_attack_unit -----------// //------------- Begin of function Unit::defend_town_detect_target --------------// // set to detect mode // void Unit::defend_town_detect_target() { action_mode2 = ACTION_DEFEND_TOWN_DETECT_TARGET; action_para2 = UNIT_DEFEND_TOWN_DETECT_COUNT; action_x_loc2 = -1; action_y_loc2 = -1; } //----------- End of function Unit::defend_town_detect_target -----------// //------------- Begin of function Unit::process_defend_town_attack_target --------------// // defend town units is only allowed to attack unit // void Unit::process_defend_town_attack_target() { err_when(action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET); if(general_defend_mode_process_attack_target()) { action_mode2 = ACTION_DEFEND_TOWN_DETECT_TARGET; action_para2 = UNIT_DEFEND_TOWN_DETECT_COUNT; action_x_loc2 = action_y_loc2 = -1; err_when(action_mode!=ACTION_STOP || action_para || action_x_loc!=-1 || action_y_loc!=-1 || cur_action==SPRITE_ATTACK); } } //----------------- End of function Unit::process_defend_town_attack_target ----------------// //------------- Begin of function Unit::process_defend_town_detect_target --------------// // process detect mode // void Unit::process_defend_town_detect_target() { err_when(action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET); err_when(action_mode!=ACTION_STOP); err_when(action_para!=0); err_when(action_x_loc!=-1 || action_y_loc!=-1 || action_x_loc2!=-1 || action_y_loc2!=-1); //----------------------------------------------------------------// // no target or target is out of detect range, so change state to // back camp //----------------------------------------------------------------// if(!action_para2) { err_when(action_misc!=ACTION_MISC_DEFEND_TOWN_RECNO || !action_misc_para); err_when(unit_mode!=UNIT_MODE_DEFEND_TOWN || !unit_mode_para); int back = 0; Town *townPtr; Unit *targetPtr; if(town_array.is_deleted(action_misc_para)) back++; else { townPtr = town_array[action_misc_para]; if(unit_array.is_deleted(townPtr->defend_target_recno)) back++; else { targetPtr = unit_array[townPtr->defend_target_recno]; if(targetPtr->action_mode!=ACTION_ATTACK_TOWN || targetPtr->action_para!=townPtr->town_recno) back++; } } if(!back) { //action_mode2 = ACTION_DEFEND_TOWN_DETECT_TARGET; action_para2 = UNIT_DEFEND_TOWN_DETECT_COUNT; return; } process_defend_town_back_town(); return; } //----------------------------------------------------------------// // defense_detecting target algorithm //----------------------------------------------------------------// int startLoc; int dimension; switch(action_para2%GAME_FRAMES_PER_DAY) { case 3: startLoc = 2;// 1-7, check 224 = 15^2-1 //### begin alex 3/10 ###// dimension = 7; //#### end alex 3/10 ####// break; case 2: startLoc = 122;// 6-8, check 168 = 17^2-11^2 dimension = 8; break; case 1: startLoc = 170;// 7-9, check 192 = 19^2-13^2 dimension = EFFECTIVE_DEFEND_TOWN_DISTANCE; break; default: action_para2--; return; } //---------------------------------------------------------------// // attack the target if target detected, or change the detect region //---------------------------------------------------------------// if(!idle_detect_attack(startLoc, dimension, 1)) // defense mode is on action_para2--; } //----------------- End of function Unit::process_defend_town_detect_target ----------------// //------------- Begin of function Unit::process_defend_town_back_town --------------// // process action to go back town // void Unit::process_defend_town_back_town() { int clearDefenseMode = 0; if(action_mode!=ACTION_ASSIGN_TO_TOWN) // the unit may become idle or unable to reach town, reactivate it { Town *townPtr; if(action_misc!=ACTION_MISC_DEFEND_TOWN_RECNO || !action_misc_para || town_array.is_deleted(action_misc_para)) clearDefenseMode++; else { townPtr = town_array[action_misc_para]; if(townPtr->nation_recno!=nation_recno) clearDefenseMode++; else { defend_town_back_town(action_misc_para); // go back to the town err_when(action_mode2!=ACTION_DEFEND_TOWN_BACK_TOWN); return; } } } else if(cur_action==SPRITE_IDLE) { if(town_array.is_deleted(action_misc_para)) clearDefenseMode++; else { defend_town_back_town(action_misc_para); err_when(action_mode2!=ACTION_DEFEND_TOWN_BACK_TOWN); return; } } err_when(!clearDefenseMode); //----------------------------------------------------------------// // clear order if the town is deleted //----------------------------------------------------------------// stop2(); reset_action_misc_para(); err_when(in_defend_town_mode()); } //----------------- End of function Unit::process_defend_town_back_town ----------------// //------------- Begin of function Unit::in_defend_town_mode --------------// // check whether the unit is in defend town mode // int Unit::in_defend_town_mode() { return (action_mode2>=ACTION_DEFEND_TOWN_ATTACK_TARGET && action_mode2<=ACTION_DEFEND_TOWN_BACK_TOWN); } //----------------- End of function Unit::in_defend_town_mode ----------------// //--------- Begin of function Unit::defend_town_back_town ---------// // set action to back town // // townRecno - recno of the town // void Unit::defend_town_back_town(short townRecno) { err_when(town_array.is_deleted(townRecno)); Town *townPtr = town_array[townRecno]; assign(townPtr->loc_x1, townPtr->loc_y1); action_mode2 = ACTION_DEFEND_TOWN_BACK_TOWN; } //----------- End of function Unit::defend_town_back_town -----------// //------------- Begin of function Unit::defend_town_follow_target --------------// // check the unit should follow the target or not // // return 0 if aborting attack the current target and go back to military camp // return 1 otherwise // int Unit::defend_town_follow_target() { err_when(unit_mode!=UNIT_MODE_DEFEND_TOWN); if(cur_action==SPRITE_ATTACK) return 1; if(town_array.is_deleted(unit_mode_para)) { stop2(); //**** BUGHERE set_mode(0); //***BUGHERE return 0; } int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); Town *townPtr = town_array[unit_mode_para]; if((curXLoccenter_x-UNIT_DEFEND_TOWN_DISTANCE) || (curXLoc>townPtr->center_x+UNIT_DEFEND_TOWN_DISTANCE) || (curYLoccenter_y-UNIT_DEFEND_TOWN_DISTANCE) || (curYLoc>townPtr->center_y+UNIT_DEFEND_TOWN_DISTANCE)) { defend_town_back_town(unit_mode_para); return 0; } return 1; } //----------- End of function Unit::defend_town_follow_target -----------// //------------- Begin of function Unit::clear_town_defend_mode --------------// // clear defend mode // void Unit::clear_town_defend_mode() { //------- cancel defense mode and continue the current action -------// action_mode2 = action_mode; action_para2 = action_para; action_x_loc2 = action_x_loc; action_y_loc2 = action_y_loc; reset_action_misc_para(); } //----------------- End of function Unit::clear_town_defend_mode ----------------// //=================================================================================================// // Monster unit's defend mode //=================================================================================================// //--------- Begin of function Unit::monster_defend_attack_unit ---------// // set to attack target // // targetRecno - recno of the target // void Unit::monster_defend_attack_unit(short targetRecno) { action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET; attack_unit(targetRecno); } //----------- End of function Unit::monster_defend_attack_unit -----------// //--------- Begin of function Unit::monster_defend_attack_firm ---------// // set monster to attack firm // // targetXLoc - x location of firm // targetYLoc - y location of firm // void Unit::monster_defend_attack_firm(int targetXLoc, int targetYLoc) { action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET; attack_firm(targetXLoc, targetYLoc); } //----------- End of function Unit::monster_defend_attack_firm -----------// //--------- Begin of function Unit::monster_defend_attack_town ---------// // set monster to attack town // // targetXLoc - x location of the town // targetYLoc - y location of the town // void Unit::monster_defend_attack_town(int targetXLoc, int targetYLoc) { action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET; attack_town(targetXLoc, targetYLoc); } //----------- End of function Unit::monster_defend_attack_town -----------// //--------- Begin of function Unit::monster_defend_attack_wall ---------// // set monster to attack wall // // targetXLoc - x location of wall // targetYLoc - y location of wall // void Unit::monster_defend_attack_wall(int targetXLoc, int targetYLoc) { action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET; attack_wall(targetXLoc, targetYLoc); } //----------- End of function Unit::monster_defend_attack_wall -----------// //--------- Begin of function Unit::monster_defend_detect_target ---------// // set to detect mode // void Unit::monster_defend_detect_target() { action_mode2 = ACTION_MONSTER_DEFEND_DETECT_TARGET; action_para2 = MONSTER_DEFEND_DETECT_COUNT; action_x_loc2 = -1; action_y_loc2 = -1; } //----------- End of function Unit::monster_defend_detect_target -----------// //--------- Begin of function Unit::monster_defend_back_firm ---------// // set to return mode // void Unit::monster_defend_back_firm(int firmXLoc, int firmYLoc) { err_when(firm_array[world.get_loc(firmXLoc, firmYLoc)->firm_recno()]->firm_id!=FIRM_MONSTER); assign(firmXLoc, firmYLoc); action_mode2 = ACTION_MONSTER_DEFEND_BACK_FIRM; } //----------- End of function Unit::monster_defend_back_firm -----------// //--------- Begin of function Unit::process_monster_defend_attack_target ---------// // proces attack mode // void Unit::process_monster_defend_attack_target() { err_when(action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET); if(general_defend_mode_process_attack_target()) { monster_defend_detect_target(); err_when(action_mode!=ACTION_STOP || action_para || action_x_loc!=-1 || action_y_loc!=-1 || cur_action==SPRITE_ATTACK); } } //----------- End of function Unit::process_monster_defend_attack_target -----------// //--------- Begin of function Unit::process_monster_defend_detect_target ---------// // process detect mode // void Unit::process_monster_defend_detect_target() { err_when(action_mode2!=ACTION_MONSTER_DEFEND_DETECT_TARGET); err_when(action_mode!=ACTION_STOP); err_when(action_para!=0); err_when(action_x_loc!=-1 || action_y_loc!=-1 || action_x_loc!=-1 || action_y_loc2!=-1); //----------------------------------------------------------------// // no target or target is out of detect range, so change state to // back camp //----------------------------------------------------------------// if(!action_para2) { err_when(action_misc!=ACTION_MISC_MONSTER_DEFEND_FIRM_RECNO || !action_misc_para); err_when(unit_mode!=UNIT_MODE_MONSTER || !unit_mode_para); int back = 0; Unit *targetPtr; FirmMonster *firmMonsterPtr; if(firm_array.is_deleted(action_misc_para)) back++; else { firmMonsterPtr = (FirmMonster*) firm_array[action_misc_para]; if(unit_array.is_deleted(firmMonsterPtr->defend_target_recno)) back++; else { targetPtr = unit_array[firmMonsterPtr->defend_target_recno]; if(targetPtr->action_mode!=ACTION_ATTACK_FIRM || targetPtr->action_para!=firmMonsterPtr->firm_recno) back++; } } if(!back) { //action_mode2 = ACTION_MONSTER_DEFEND_DETECT_TARGET; action_para2 = MONSTER_DEFEND_DETECT_COUNT; return; } process_monster_defend_back_firm(); return; } //----------------------------------------------------------------// // defense_detecting target algorithm //----------------------------------------------------------------// int startLoc; int dimension; switch(action_para2%GAME_FRAMES_PER_DAY) { case 3: startLoc = 2;// 1-7, check 224 = 15^2-1 //### begin alex 3/10 ###// dimension = 7; //#### end alex 3/10 ####// break; case 2: startLoc = 122;// 6-8, check 168 = 17^2-11^2 dimension = 8; break; case 1: startLoc = 170;// 7-9, check 192 = 19^2-13^2 dimension = EFFECTIVE_MONSTER_DEFEND_FIRM_DISTANCE; break; default: action_para2--; return; } //---------------------------------------------------------------// // attack the target if target detected, or change the detect region //---------------------------------------------------------------// if(!idle_detect_attack(startLoc, dimension, 1)) // defense mode is on action_para2--; } //----------- End of function Unit::process_monster_defend_detect_target -----------// //--------- Begin of function Unit::process_monster_defend_back_firm ---------// // process return mode // void Unit::process_monster_defend_back_firm() { int clearDefendMode = 0; if(action_mode!=ACTION_ASSIGN_TO_FIRM) // the unit may become idle or unable to reach firm, reactivate it { Firm *firmPtr; if(action_misc!=ACTION_MISC_MONSTER_DEFEND_FIRM_RECNO || !action_misc_para || firm_array.is_deleted(action_misc_para)) clearDefendMode++; else { firmPtr = firm_array[action_misc_para]; if(firmPtr->firm_id!=FIRM_MONSTER || firmPtr->nation_recno!=nation_recno) clearDefendMode++; else { monster_defend_back_firm(firmPtr->loc_x1, firmPtr->loc_y1); // go back to the military camp err_when(action_mode2!=ACTION_MONSTER_DEFEND_BACK_FIRM); return; } } } else if(cur_action==SPRITE_IDLE) { if(firm_array.is_deleted(action_misc_para)) clearDefendMode++; else { Firm *firmPtr = firm_array[action_misc_para]; monster_defend_back_firm(firmPtr->loc_x1, firmPtr->loc_y1); err_when(action_mode2!=ACTION_MONSTER_DEFEND_BACK_FIRM); return; } } err_when(!clearDefendMode); //----------------------------------------------------------------// // clear order if the camp is deleted //----------------------------------------------------------------// stop2(); reset_action_misc_para(); err_when(in_monster_defend_mode()); } //----------- End of function Unit::process_monster_defend_back_firm -----------// //------------- Begin of function Unit::in_monster_defend_mode --------------// // check whether the unit is in defend mode // int Unit::in_monster_defend_mode() { return (action_mode2>=ACTION_MONSTER_DEFEND_ATTACK_TARGET && action_mode2<=ACTION_MONSTER_DEFEND_BACK_FIRM); } //----------- End of function Unit::in_monster_defend_mode -----------// //------------- Begin of function Unit::monster_defend_follow_target --------------// // make decision to choose to follow target or return // // return 0 if aborting attack the current target and go back to military camp // return 1 otherwise // int Unit::monster_defend_follow_target() { //######## begin trevor 22/8 ##########// err_when( unit_mode!=UNIT_MODE_MONSTER || !unit_mode_para ); if(cur_action==SPRITE_ATTACK) return 1; /* if(firm_array.is_deleted(action_misc_para)) { stop2(); //**** BUGHERE //set_mode(0); //***BUGHERE if(monster_array.is_deleted(unit_mode_para)) return 0; Monster *monsterPtr = monster_array[unit_mode_para]; monsterPtr->firm_recno = 0; return 0; } */ //######## end trevor 22/8 ##########// //--------------------------------------------------------------------------------// // choose to return to firm //--------------------------------------------------------------------------------// int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); Firm *firmPtr = firm_array[action_misc_para]; if((curXLoccenter_x-MONSTER_DEFEND_FIRM_DISTANCE) || (curXLoc>firmPtr->center_x+MONSTER_DEFEND_FIRM_DISTANCE) || (curYLoccenter_y-MONSTER_DEFEND_FIRM_DISTANCE) || (curYLoc>firmPtr->center_y+MONSTER_DEFEND_FIRM_DISTANCE)) { monster_defend_back_firm(firmPtr->loc_x1, firmPtr->loc_y1); return 0; } return 1; } //----------- End of function Unit::monster_defend_follow_target -----------// //------------- Begin of function Unit::clear_monster_defend_mode --------------// // clear defend mode // void Unit::clear_monster_defend_mode() { err_when(!in_monster_defend_mode()); //------- cancel defense mode and continue the current action -------// action_mode2 = action_mode; action_para2 = action_para; action_x_loc2 = action_x_loc; action_y_loc2 = action_y_loc; reset_action_misc_para(); } //----------------- End of function Unit::clear_monster_defend_mode ----------------//