//--------- Begin of function Unit::think_build_camp --------// // // Think about building a camp next to the town which is // closest to the unit. // int Unit::think_build_camp() { //---- select a town to build the camp ---// Nation* ownNation = nation_array[nation_recno]; Town *townPtr, *bestTown=NULL; int curRating=0, bestRating=0; int regionId = world.get_region_id( next_x_loc(), next_y_loc() ); int curXLoc = next_x_loc(), curYLoc = next_y_loc(); for( int i=ownNation->ai_town_count-1 ; i>=0 ; i-- ) { townPtr = town_array[ ownNation->ai_town_array[i] ]; if( townPtr->region_id != regionId ) continue; if( !townPtr->is_base_town || townPtr->no_neighbor_space ) continue; curRating = world.distance_rating(curXLoc, curYLoc, townPtr->center_x, townPtr->center_y ); if( curRating > bestRating ) { bestRating = curRating; bestTown = townPtr; } } if( bestTown ) return bestTown->ai_build_neighbor_firm(FIRM_CAMP); return 0; }
// --------- 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::ai_move_to_nearby_town --------// // // [int] shouldAssign - this tells whether the unit should be assigned // to the town. (default: 0) // void Unit::ai_move_to_nearby_town(int shouldAssign) { //---- look for towns to move to -----// Nation* ownNation = nation_array[nation_recno]; Town *townPtr, *bestTown=NULL; int regionId = world.get_region_id( next_x_loc(), next_y_loc() ); int curDistance, curRating, bestRating=0; int curXLoc = next_x_loc(), curYLoc = next_y_loc(); for( int i=town_array.size() ; i>0 ; i-- ) // can't use ai_town_array[] because this function will be called by Unit::betray() when a unit defected to the player's kingdom { if( town_array.is_deleted(i) ) continue; townPtr = town_array[i]; if( townPtr->nation_recno != nation_recno ) continue; if( townPtr->region_id != regionId ) continue; //-------------------------------------// curDistance = misc.points_distance(curXLoc, curYLoc, townPtr->center_x, townPtr->center_y ); if( curDistance < 10 ) // no need to move if the unit is already close enough to the town. return; curRating = 100 - 100 * curDistance / MAX_WORLD_X_LOC; curRating += townPtr->population; if( race_id == townPtr->race_id ) curRating += 100; //-------------------------------------// if( curRating > bestRating ) { bestRating = curRating; bestTown = townPtr; } } if( bestTown ) { if( shouldAssign ) assign(bestTown->loc_x1, bestTown->loc_y1); else move(bestTown->loc_x1, bestTown->loc_y1); } }
//---------- Begin of function UnitB::process_blocked -----// // // retry move to destination if the unit is blocked // void UnitB::process_blocked() { if(number_of_times_being_blocked++ > MAX_UNIT_BLOCKED_TIME || (next_x_loc() == move_to_loc_x && next_y_loc() == move_to_loc_y) || ((abs(move_to_loc_x - next_x_loc()) <= obj_loc_width()) && (abs(move_to_loc_y - next_y_loc()) <= obj_loc_height()) && !can_move(move_to_loc_x, move_to_loc_y) && !checking_who_occupy_the_place_i_want_to_go(move_to_loc_x, move_to_loc_y))) { set_no_longer_blocked(); stop_move(); } else move_to(move_to_loc_x, move_to_loc_y); }
//--------- Begin of function UnitMonster::assign_to_firm --------// // int UnitMonster::assign_to_firm() { int i, firmCount=firm_array.size(); Firm* firmPtr; int curXLoc = next_x_loc(), curYLoc = next_y_loc(); BYTE regionId = world.get_region_id(curXLoc, curYLoc); int firmRecno = m.random(firm_array.size())+1; for( i=0 ; i<firmCount ; i++ ) { if( ++firmRecno > firmCount ) firmRecno = 1; if( firm_array.is_deleted(firmRecno) ) continue; firmPtr = firm_array[firmRecno]; if( firmPtr->region_id != regionId ) continue; if( firmPtr->firm_id == FIRM_MONSTER ) { if( ((FirmMonster*)firmPtr)->can_assign_monster(sprite_recno) ) { group_order_monster(firmPtr->loc_x1, firmPtr->loc_y1, 2); // 2-the action is assign return 1; } } } return 0; }
//------------- 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((curXLoc<townPtr->center_x-UNIT_DEFEND_TOWN_DISTANCE) || (curXLoc>townPtr->center_x+UNIT_DEFEND_TOWN_DISTANCE) || (curYLoc<townPtr->center_y-UNIT_DEFEND_TOWN_DISTANCE) || (curYLoc>townPtr->center_y+UNIT_DEFEND_TOWN_DISTANCE)) { defend_town_back_town(unit_mode_para); return 0; } return 1; }
//--------- Begin of function UnitMarine::is_on_coast ---------// // // Return whether the unit is on the coast and ready for unloading. // int UnitMarine::is_on_coast() { Location *locPtr; int xShift, yShift, checkXLoc, checkYLoc, found=0; int curXLoc = next_x_loc(); // ship location int curYLoc = next_y_loc(); for(int i=2; i<=9; i++) // checking for the surrouding location { m.cal_move_around_a_point(i, 3, 3, xShift, yShift); checkXLoc = curXLoc + xShift; checkYLoc = curYLoc + yShift; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) continue; locPtr = world.get_loc(checkXLoc, checkYLoc); if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN && // a territory nearby locPtr->walkable()) { return 1; } } return 0; }
//--------- Begin of function Unit::detect_basic_info ---------// // int Unit::detect_basic_info() { //--- detect pressing on the name to center the unit on the screen ---// if( is_visible() && mouse.single_click( INFO_X1, INFO_Y1, INFO_X2, INFO_Y1+21 ) ) { world.go_loc( next_x_loc(), next_y_loc() ); return 1; } //-------- detect resign button ----------// // ###### patch begin Alex 10/1 ########// // if( is_own() && rank_id != RANK_KING ) if( nation_recno == nation_array.player_recno && rank_id != RANK_KING ) { if( button_resign.detect(KEY_DEL) ) { group_resign(); return 1; } } // ###### patch end Alex 10/1 ########// return 0; }
//--------- Begin of function UnitGod::viking_summon_tornado ---------// // void UnitGod::viking_summon_tornado() { // ######## begin Gilbert 14/10 ########// short xLoc = next_x_loc(); short yLoc = next_y_loc(); char dir = final_dir % 8; // ######## end Gilbert 14/10 ########// // put a tornado one location ahead if( dir == 0 || dir == 1 || dir == 7 ) if( yLoc > 0 ) yLoc--; if( dir >= 1 && dir <= 3 ) if( xLoc < MAX_WORLD_X_LOC-1 ) xLoc++; if( dir >= 3 && dir <= 5 ) if( yLoc < MAX_WORLD_Y_LOC-1) yLoc++; if( dir >= 5 && dir <= 7 ) if( xLoc > 0 ) xLoc--; tornado_array.add_tornado( xLoc, yLoc, 600 ); magic_weather.cast_wind(10, 1, dir * 45 ); // 10 days }
//------- Begin of function UnitMonster::die -------// // void UnitMonster::die() { if( !is_visible() ) return; //--- check if the location where the unit dies already has an item ---// int xLoc = cur_x_loc(); int yLoc = cur_y_loc(); if( !world.get_loc(xLoc, yLoc)->can_build_site() ) { int txLoc, tyLoc, foundFlag=0; for( tyLoc=max(yLoc-1,0) ; tyLoc<=min(yLoc+1,MAX_WORLD_Y_LOC-1) && !foundFlag ; tyLoc++ ) { for( txLoc=max(xLoc-1,0) ; txLoc<=min(xLoc+1,MAX_WORLD_X_LOC-1) ; txLoc++ ) { if( world.get_loc(txLoc,tyLoc)->can_build_site() ) { xLoc = txLoc; yLoc = tyLoc; foundFlag = 1; break; } } } if( !foundFlag ) return; } //--- when a general monster is killed, it leaves gold coins ---// if( !nation_recno && get_monster_id() != 0) // to skip monster_res[ get_monster_id() ] error in test game 2 { MonsterInfo* monsterInfo = monster_res[ get_monster_id() ]; if( rank_id == RANK_GENERAL ) { int goldAmount = 2 * max_hit_points * monsterInfo->level * (100+m.random(30)) / 100; site_array.add_site( xLoc, yLoc, SITE_GOLD_COIN, goldAmount ); site_array.ai_get_site_object(); // ask AI units to get the gold coins } //--- when a king monster is killed, it leaves a scroll of power ---// else if( rank_id == RANK_KING ) { king_leave_scroll(); } } //---------- add news ----------// if( rank_id == RANK_KING ) news_array.monster_king_killed( get_monster_id(), next_x_loc(), next_y_loc() ); }
//------------- Begin of function Unit::sound --------------// // void Unit::sound(const char* soundCode) { if( se_res.mark_command_time() ) { se_res.far_sound( next_x_loc(), next_y_loc(), 1, 'S', sprite_id, soundCode ); } }
//------- Begin of function Unit::think_change_attack_target -------// // // When the unit is attacking a firm or town, look out for enemy units // to attack. Enemy units should be attacked first. // int Unit::think_change_attack_target() { err_when( !nation_recno ); // only for nation units //----------------------------------------------// int attackRange = MAX(attack_range, 8); int attackScanRange = attackRange*2+1; int xOffset, yOffset; int xLoc, yLoc; Location* locPtr; int curXLoc = next_x_loc(), curYLoc = next_y_loc(); BYTE regionId = world.get_region_id(curXLoc, curYLoc); for( int i=2 ; i<attackScanRange*attackScanRange ; i++ ) { m.cal_move_around_a_point(i, attackScanRange, attackScanRange, xOffset, yOffset); xLoc = curXLoc + xOffset; yLoc = curYLoc + yOffset; xLoc = MAX(0, xLoc); xLoc = MIN(MAX_WORLD_X_LOC-1, xLoc); yLoc = MAX(0, yLoc); yLoc = MIN(MAX_WORLD_Y_LOC-1, yLoc); locPtr = world.get_loc(xLoc, yLoc); if( locPtr->region_id != regionId ) continue; //----- if there is a unit on the location ------// if( locPtr->has_unit(UNIT_LAND) ) { int unitRecno = locPtr->unit_recno(UNIT_LAND); if( unit_array.is_deleted(unitRecno) ) continue; if( unit_array[unitRecno]->nation_recno != nation_recno && idle_detect_unit_checking(unitRecno) ) { save_original_action(); original_target_x_loc = xLoc; original_target_y_loc = yLoc; attack_unit(xLoc, yLoc); return 1; } } } return 0; }
//--------- Begin of function Unit::ai_move_to_nearby_firm --------// // // <int> firmId - move to this firm. // [int] firmId2 - optional. If given will also move to this firm. // void Unit::ai_move_to_nearby_firm(int firmId, int firmId2) { //---- look for towns to move to -----// Nation* ownNation = nation_array[nation_recno]; Firm *firmPtr, *bestFirm=NULL; int regionId = world.get_region_id( next_x_loc(), next_y_loc() ); int curRating, bestRating=0; int curXLoc = next_x_loc(), curYLoc = next_y_loc(); for( int i=firm_array.size() ; i>0 ; i-- ) // can't use ai_firm_array[] because this function will be called by Unit::betray() when a unit defected to the player's kingdom { if( firm_array.is_deleted(i) ) continue; firmPtr = firm_array[i]; if( firmPtr->nation_recno != nation_recno ) continue; if( firmPtr->region_id != regionId ) continue; if( firmPtr->firm_id != firmId && firmPtr->firm_id != firmId2 ) continue; //-------------------------------------// curRating = world.distance_rating( curXLoc, curYLoc, firmPtr->center_x, firmPtr->center_y ); if( race_id == firmPtr->race_id ) curRating += 100; //-------------------------------------// if( curRating > bestRating ) { bestRating = curRating; bestFirm = firmPtr; } } if( bestFirm ) move(bestFirm->loc_x1, bestFirm->loc_y1); }
// -------- begin of function Unit::explore_area --------// // // explore whole rectangle // called when init_sprite, change nation, spy::end_camouflage // void Unit::explore_area() { //------ unveil the area where the unit is added to ------// if( explore_for_player() ) { int scoutRange = item.ability(ITEM_ABILITY_SCOUT_RANGE); // do not call use_now, let next_day to use its energy world.unveil( next_x_loc()-scoutRange, next_y_loc()-scoutRange, next_x_loc() + loc_width + scoutRange -1, next_y_loc() + loc_height + scoutRange -1 ); world.visit(next_x_loc(), next_y_loc(), next_x_loc()+loc_width-1, next_y_loc()+loc_height-1, unit_res[unit_id]->visual_range + scoutRange, unit_res[unit_id]->visual_extend); } }
//--------- Begin of function Unit::ai_escape_fire --------// // // Move away if the unit currently stands on a burning ground. // int Unit::ai_escape_fire() { if(cur_action!=SPRITE_IDLE) return 0; if(mobile_type!=UNIT_LAND) return 0; Location *locPtr = world.get_loc(next_x_loc(), next_y_loc()); if( !locPtr->fire_str() ) return 0; //--------------------------------------------// int checkLimit = 400; // checking for 400 location int xShift, yShift, checkXLoc, checkYLoc; int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); for(int i=2; i<checkLimit; i++) { misc.cal_move_around_a_point(i, 20, 20, xShift, yShift); checkXLoc = curXLoc + xShift; checkYLoc = curYLoc + yShift; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) continue; if(!locPtr->can_move(mobile_type)) continue; locPtr = world.get_loc(checkXLoc, checkYLoc); if( locPtr->fire_str()==0 ) // move to a safe place now { move_to(checkXLoc, checkYLoc); return 1; } } return 0; }
//--------- Begin of function Unit::detect_unit_profile ---------// // int Unit::detect_unit_profile() { if( is_visible() && mouse.single_click( INFO_X1, INFO_Y1+54, INFO_X2, INFO_Y1+97 ) ) { world.go_loc( next_x_loc(), next_y_loc() ); return 1; } return 0; }
int Unit::think_assign_weapon_to_camp() { Nation *nationPtr = nation_array[nation_recno]; FirmCamp *firmCamp, *bestCamp=NULL; int curRating=0, bestRating=0; int regionId = world.get_region_id( next_x_loc(), next_y_loc() ); int curXLoc = next_x_loc(), curYLoc = next_y_loc(); for( int i=0 ; i<nationPtr->ai_camp_count ; i++ ) { firmCamp = firm_array[ nationPtr->ai_camp_array[i] ]->cast_to_FirmCamp(); if( firmCamp->region_id != regionId || firmCamp->is_soldier_full() ) continue; if( !firmCamp->can_accept_assign(sprite_recno) ) continue; //-------- calculate the rating ---------// curRating = world.distance_rating(curXLoc, curYLoc, firmCamp->center_x, firmCamp->center_y ); curRating += (MAX_SOLDIER - firmCamp->soldier_count) * 10; //-------------------------------------// if( curRating > bestRating ) { bestRating = curRating; bestCamp = firmCamp; } } //-----------------------------------// if( bestCamp ) { assign(bestCamp->loc_x1, bestCamp->loc_y1); return 1; } return 0; }
//--------- Begin of function Unit::region_id ---------// // // Return the region id. of this unit. // BYTE Unit::region_id() { if( is_visible() ) { return world.get_region_id( next_x_loc(), next_y_loc() ); } else { if( unit_mode == UNIT_MODE_OVERSEE ) return firm_array[unit_mode_para]->region_id; } return 0; }
//-------- Begin of function Unit::should_show_info ------// // int Unit::should_show_info() { if( config.show_ai_info || is_own() ) return 1; //---- if there is a phoenix of the player over this firm ----// if( nation_array.player_recno && (~nation_array)->revealed_by_phoenix(next_x_loc(), next_y_loc()) ) { return 1; } return 0; }
//--------- Begin of function UnitGod::detect_info ---------// // void UnitGod::detect_info() { if( detect_basic_info() ) return; if( detect_unit_profile() ) return; if( !is_own() ) return; if( game.game_mode == GAME_TEST ) return; if( god_res[god_id]->can_cast_power ) { // ###### begin Gilbert 14/10 ######// int rc=0; char castPowerType = 0; if( button_cast.detect() ) { // cast_power_type = 1; castPowerType = 1; rc = 1; } if( button_cast2.detect() ) { castPowerType = 2; //cast_power_type = 2; //cast_origin_x = cur_x_loc(); //cast_origin_y = cur_y_loc(); rc = 1; } //----------------------------------------// if( rc && castPowerType) { if( god_id == GOD_VIKING && castPowerType == 1 ) // summon rain, summon immediately, no need to select target go_cast_power(next_x_loc(), next_y_loc(), castPowerType, COMMAND_PLAYER); else power.issue_command(COMMAND_GOD_CAST_POWER, sprite_recno, castPowerType); } // ###### end Gilbert 14/10 ######// } }
//----------- Begin of function UnitB::process_idle----------// // // when a unit is idling, if it is block, process block // if it is in formation but fnot yet reach destination, go there again // void UnitB::process_idle() { cur_action = SPRITE_IDLE; if(is_blocked() && cur_order.mode != UNIT_ATTACK) process_blocked(); else if(/*is_in_formation() && */ is_blocked() && ((next_x_loc() != move_to_loc_x) || (next_y_loc() != move_to_loc_y)) && can_move(move_to_loc_x, move_to_loc_y)) move_to(move_to_loc_x, move_to_loc_y); else Sprite::process_idle(); }
//--------- Begin of function Unit::ship_leave_beach ---------// void Unit::ship_leave_beach(int shipOldXLoc, int shipOldYLoc) { err_when(cur_x!=next_x || cur_y!=next_y); UnitMarine *shipPtr = (UnitMarine*) this; err_when(!shipPtr->in_beach && shipPtr->extra_move_in_beach==EXTRA_MOVE_FINISH); //--------------------------------------------------------------------------------// // scan for location to leave the beach //--------------------------------------------------------------------------------// int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); int xShift, yShift, checkXLoc, checkYLoc, found=0; Location *locPtr; //------------- find a location to leave the beach ------------// for(int i=2; i<=9; i++) { misc.cal_move_around_a_point(i, 3, 3, xShift, yShift); checkXLoc = curXLoc + xShift; checkYLoc = curYLoc + yShift; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) continue; if(checkXLoc%2 || checkYLoc%2) continue; locPtr = world.get_loc(checkXLoc, checkYLoc); if(terrain_res[locPtr->terrain_id]->average_type==TERRAIN_OCEAN && locPtr->can_move(mobile_type)) { found++; break; } } if(!found) return; // no suitable location, wait until finding suitable location //---------------- leave now --------------------// set_dir(shipOldXLoc, shipOldYLoc, checkXLoc, checkYLoc); set_ship_extra_move(); go_x = checkXLoc*ZOOM_LOC_WIDTH; go_y = checkYLoc*ZOOM_LOC_HEIGHT; err_when(cur_x==go_x && cur_y==go_y); }
//----------- Begin of function Unit::get_cur_loc -----------// // // <short&> xLoc, yLoc - reference vars for returning the // location of this unit // // return : 0 - if this unit is invisible // 1 - if a location has been returned. // int Unit::get_cur_loc(short& xLoc, short& yLoc) { if( is_visible() ) { xLoc = next_x_loc(); // update location yLoc = next_y_loc(); } else if( unit_mode == UNIT_MODE_OVERSEE || unit_mode==UNIT_MODE_CONSTRUCT_FIRM || unit_mode == UNIT_MODE_IN_HARBOR ) { Firm* firmPtr = firm_array[unit_mode_para]; xLoc = firmPtr->center_x; yLoc = firmPtr->center_y; } else if( unit_mode==UNIT_MODE_CONSTRUCT_TOWN ) { Town* townPtr = town_array[unit_mode_para]; xLoc = townPtr->center_x; yLoc = townPtr->center_y; } else if( unit_mode == UNIT_MODE_ON_SHIP ) { Unit* unitPtr = unit_array[unit_mode_para]; if(unitPtr->is_visible()) { xLoc = unitPtr->next_x_loc(); yLoc = unitPtr->next_y_loc(); } else { err_when(unitPtr->unit_mode!=UNIT_MODE_IN_HARBOR); Firm *firmPtr = firm_array[unitPtr->unit_mode_para]; xLoc = firmPtr->center_x; yLoc = firmPtr->center_y; } } else return 0; return 1; }
//--------- Begin of function Unit::ai_build_firm --------// // // Order this unit to build a camp in its region. // int Unit::ai_build_firm() { //--- don't build if the race of the nation and the unit is different ----// if( nation_array[nation_recno]->is_human() != is_human() ) return 0; //---------------------------------------------------------------// int firmId; if( is_human() ) firmId = FIRM_FORT; else firmId = FIRM_LAIR; if( !firm_res[firmId]->can_build(sprite_recno) ) return 0; //--- to prevent building more than one camp at the same time ---// int curRegionId = region_id(); Nation* ownNation = nation_array[nation_recno]; if( ownNation->is_action_exist( ACTION_AI_BUILD_FIRM, firmId, curRegionId ) ) return 0; //------- locate a place for the camp --------// FirmInfo* firmInfo = firm_res[firmId]; char teraMask = UnitRes::mobile_type_to_mask(UNIT_LAND); int xLoc=next_x_loc(), yLoc=next_y_loc(); if( world.locate_space(xLoc, yLoc, xLoc, yLoc, firmInfo->loc_width+INTER_PLACE_SPACE*2, firmInfo->loc_height+INTER_PLACE_SPACE*2, // leave at least one location space around the building UNIT_LAND, curRegionId, 1) ) { return ownNation->add_action( xLoc, yLoc, -1, -1, ACTION_AI_BUILD_FIRM, firmId, 1, sprite_recno ); } return 0; }
//--------- Begin of function Unit::push_order ---------// // // Note: the stack only has space for one Order object. // void Unit::push_order() { err_when( has_pushed_order() > 0 ); // cannot push when the only one stack space is used pushed_order = cur_order; // ##### begin Gilbert 31/5 ########// // if the unit is stopped, store current location, used when resuming the action if( pushed_order.mode == UNIT_STOP ) { pushed_order.set(UNIT_STOP, -2, next_x_loc(), next_y_loc() ); // para = -2; to identify resume move, see execute_attack } // ##### end Gilbert 31/5 ########/ cur_order.set(UNIT_STOP); stop_move(); }
//------------- 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((curXLoc<firmPtr->center_x-MONSTER_DEFEND_FIRM_DISTANCE) || (curXLoc>firmPtr->center_x+MONSTER_DEFEND_FIRM_DISTANCE) || (curYLoc<firmPtr->center_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; }
//------ Begin of function Unit::handle_blocked_same_target_attack ---------// // the target of the blocked unit and this unit are same // // <Unit*> unitPtr - pointer to blocking uit // <Unit*> targetPtr - pointer to target unit // void Unit::handle_blocked_same_target_attack(Unit* unitPtr, Unit* targetPtr) { //----------------------------------------------------------// // this unit is now waiting and the unit pointed by unitPtr // is attacking the unit pointed by targetPtr //----------------------------------------------------------// err_when(cur_x%ZOOM_LOC_WIDTH || cur_y%ZOOM_LOC_HEIGHT); err_when(cur_x!=next_x || cur_y!=next_y); err_when(cur_x==go_x && cur_y==go_y); if(space_for_attack(action_x_loc, action_y_loc, targetPtr->mobile_type, targetPtr->sprite_info->loc_width, targetPtr->sprite_info->loc_height)) { err_when(action_x_loc!=action_x_loc2 || action_y_loc!=action_y_loc2); search_or_stop(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_TO_ATTACK, targetPtr->sprite_recno); //search(move_to_x_loc, move_to_y_loc, 1, SEARCH_MODE_TO_ATTACK, targetPtr->sprite_recno); } else if(in_any_defense_mode()) { err_when(action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET && action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET); general_defend_mode_detect_target(); } else if(m.points_distance(next_x_loc(), next_y_loc(), action_x_loc, action_y_loc)<ATTACK_DETECT_DISTANCE) { //------------------------------------------------------------------------// // if the target is within the detect range, stop the unit's action to detect // another target if any exist. In case, there is no other target, the unit // will still attack the original target since it is the only target in the // detect range //------------------------------------------------------------------------// stop2(KEEP_DEFENSE_MODE); } else set_wait(); // set wait to stop the movement }
void UnitMarine::process_extra_move() { static short vector_x_array[] = { 0, 1, 1, 1, 0, -1, -1, -1}; // default vectors, temporary only static short vector_y_array[] = {-1, -1, 0, 1, 1, 1, 0, -1}; if(!match_dir()) // process turning return; if(cur_x!=go_x || cur_y!=go_y) { //------------------------------------------------------------------------// // set cargo_recno, extra_move_in_beach //------------------------------------------------------------------------// if(cur_x==next_x && cur_y==next_y) { int goXLoc = go_x>>ZOOM_X_SHIFT_COUNT; int goYLoc = go_y>>ZOOM_Y_SHIFT_COUNT; if(!world.get_loc(goXLoc, goYLoc)->can_move(mobile_type)) { go_x = next_x; go_y = next_y; return; } int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); world.set_unit_recno(curXLoc, curYLoc, mobile_type, 0); world.set_unit_recno(goXLoc, goYLoc, mobile_type, sprite_recno); next_x = go_x; next_y = go_y; err_when( ((curXLoc%2)|(curYLoc%2)) + ((goXLoc%2)|(goYLoc%2)) != 1); // one pair location must be even, another is not even in_beach = !(curXLoc%2 || curYLoc%2); if(goXLoc%2 || goYLoc%2) // not even location extra_move_in_beach = EXTRA_MOVING_IN; else // even location extra_move_in_beach = EXTRA_MOVING_OUT; } //else // int debug = 0; //---------- process moving -----------// short stepX = sprite_info->speed; short stepY = sprite_info->speed; short vectorX = vector_x_array[final_dir] * sprite_info->speed; // cur_dir may be changed in the above set_next() call short vectorY = vector_y_array[final_dir] * sprite_info->speed; if(abs(cur_x-go_x) <= stepX) cur_x = go_x; else cur_x += vectorX; if(abs(cur_y-go_y) <= stepY) cur_y = go_y; else cur_y += vectorY; err_when(extra_move_in_beach!=EXTRA_MOVING_IN && extra_move_in_beach!=EXTRA_MOVING_OUT); err_when(cur_action!=SPRITE_SHIP_EXTRA_MOVE); }
//--------- Begin of function UnitMarine::extra_move ---------// void UnitMarine::extra_move() { static char offset[3] = {0, 1, -1}; int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); int vecX = action_x_loc2 - curXLoc; int vecY = action_y_loc2 - curYLoc; int checkXLoc, checkYLoc, i, found=0; if(vecX==0 || vecY==0) { if(vecX==0) { vecY /= abs(vecY); checkYLoc = curYLoc + vecY; } else // vecY==0 { vecX /= abs(vecX); checkXLoc = curXLoc + vecX; } for(i=0; i<3; i++) { if(vecX==0) checkXLoc = curXLoc + offset[i]; else checkYLoc = curYLoc + offset[i]; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) continue; if(world.get_loc(checkXLoc, checkYLoc)->can_move(mobile_type)) { found++; break; } } } else { vecX /= abs(vecX); vecY /= abs(vecY); checkXLoc = curXLoc + vecX; checkYLoc = curYLoc + vecY; if(world.get_loc(checkXLoc, checkYLoc)->can_move(mobile_type)) found++; } if(!found) return; set_dir(curXLoc, curYLoc, checkXLoc, checkYLoc); cur_action = SPRITE_SHIP_EXTRA_MOVE; go_x = checkXLoc*ZOOM_LOC_WIDTH; go_y = checkYLoc*ZOOM_LOC_HEIGHT; err_when(cur_x==go_x && cur_y==go_y); //extra_move_in_beach = EXTRA_MOVING_IN; }
//--------- Begin of function UnitMarine::unloading_unit ---------// // // <int> isAll - 1 for unload all the units // - otherwise 0 // <int> unitSeqId - if(isAll==0) unitSeqId+1 is the recno of the // selected unit in unit_recno_array[] // int UnitMarine::unloading_unit(int isAll, int unitSeqId) { if( !is_on_coast() ) return 0; //-------------------------------------------------------------------------// // return if no territory is nearby the ship //-------------------------------------------------------------------------// int curXLoc = next_x_loc(); // ship location int curYLoc = next_y_loc(); int unprocess = isAll ? unit_count : 1; Unit *unitPtr = isAll ? unit_array[unit_recno_array[unprocess-1]] : unit_array[unit_recno_array[unitSeqId]]; Location *locPtr; int xShift, yShift, checkXLoc, checkYLoc; int regionId = 0; // unload all the units in the same territory int found, i = 2; int sqtSize = 3, sqtArea = sqtSize*sqtSize; #ifdef DEBUG long debugCount = 0L; #endif if(isAll && nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button. power.reset_selection(); while(unprocess) // using the calculated 'i' to reduce useless calculation { err_when(debugCount++ > 4*long(MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC)); m.cal_move_around_a_point(i, MAX_WORLD_X_LOC, MAX_WORLD_Y_LOC, xShift, yShift); checkXLoc = curXLoc+xShift; checkYLoc = curYLoc+yShift; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) { i++; continue; } locPtr = world.get_loc(checkXLoc, checkYLoc); //-------------------------------------------------------------------------// // check for space to unload the unit //-------------------------------------------------------------------------// if(!regionId || locPtr->region_id == regionId) { if(locPtr->walkable()) found = 1; if(locPtr->can_move(UNIT_LAND))//unitPtr->mobile_type)) { regionId = locPtr->region_id; unitPtr->init_sprite(checkXLoc, checkYLoc); unitPtr->set_mode(0); if( isAll && nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button. { unitPtr->selected_flag = 1; // mark selected if unload all unit_array.selected_count++; if( !unit_array.selected_recno ) unit_array.selected_recno = unitPtr->sprite_recno; } unprocess--; unit_count--; if(unprocess) unitPtr = unit_array[unit_recno_array[unprocess-1]]; // point to next unit else break; // finished, all have been unloaded } } //-------------------------------------------------------------------------// // stop checking if there is totally bouned by unacessible location //-------------------------------------------------------------------------// if(i==sqtArea) { if(found) { found = 0; // reset found sqtSize += 2; sqtArea = sqtSize*sqtSize; } else // no continuous location for the unit to unload, some units can't be unloaded return 0; } i++; } //-------- display info --------// if( nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button. info.disp(); return 1; }