//------- Begin of function Tornado::hit_building -----// // building means firm or town // void Tornado::hit_building() { short damageXLoc = damage_x_loc(); short damageYLoc = damage_y_loc(); if( damageXLoc < 0 || damageXLoc >= world.max_x_loc || damageYLoc < 0 || damageYLoc >= world.max_y_loc) return; Location* locPtr = world.get_loc(damageXLoc, damageYLoc); // ##### begin Gilbert 30/10 #####// if(locPtr->is_firm() ) // && firm_res[(firmPtr=firm_array[locPtr->firm_recno()])->firm_id]->buildable ) { Firm *firmPtr = firm_array[locPtr->firm_recno()]; firmPtr->hit_points -= attack_damage*2; if( firmPtr->hit_points <= 0) { firmPtr->hit_points = (float) 0; se_res.sound(firmPtr->center_x, firmPtr->center_y, 1, 'F', firmPtr->firm_id, "DIE" ); firm_array.del_firm(locPtr->firm_recno()); } } if( locPtr->is_town() ) { Town *townPtr = town_array[locPtr->town_recno()]; if( (life_time % 30) == 0 ) townPtr->kill_town_people(0); } // ##### end Gilbert 30/10 #####// }
void CampaignEastWest::plot_d1_create_game() { // reduce cash (~nation_array)->cash = (~nation_array)->cash / 4; // reduce mineral if the mine is owned by the player for( int i = 1; i <= site_array.size(); ++i ) { if( site_array.is_deleted(i) ) continue; Site *sitePtr = site_array[i]; if( sitePtr->site_type == SITE_RAW && sitePtr->has_mine ) { Location *locPtr = world.get_loc(sitePtr->map_x_loc, sitePtr->map_y_loc); err_when( !locPtr->is_firm() ); Firm *firmPtr = firm_array[locPtr->firm_recno()]; if( firmPtr->is_own() ) { sitePtr->reserve_qty = sitePtr->reserve_qty / 10; if( firmPtr->cast_to_FirmMine() ) { firmPtr->cast_to_FirmMine()->reserve_qty = (float)sitePtr->reserve_qty; } else if( firmPtr->cast_to_FirmMonsterAlchemy() ) { firmPtr->cast_to_FirmMonsterAlchemy()->reserve_qty = (float)sitePtr->reserve_qty; } } } } }
//------- Begin of function Bullet::hit_building -----// // building means firm or town // // ###### begin Gilbert 14/5 #########// void Bullet::hit_building(short x, short y) { Location* locPtr = world.get_loc(x, y); if(locPtr->is_firm()) { Firm *firmPtr = firm_array[locPtr->firm_recno()]; // ##### begin Gilbert 3/9 #########// if( !firmPtr || !nation_array.should_attack(nation_recno, firmPtr->nation_recno) ) // ##### end Gilbert 3/9 #########// return; } else if(locPtr->is_town()) { Town *townPtr = town_array[locPtr->town_recno()]; // ##### begin Gilbert 3/9 #########// if( !townPtr || !nation_array.should_attack(nation_recno, townPtr->nation_recno) ) // ##### end Gilbert 3/9 #########// return; } else return; float attackDamage = attenuated_damage(x * ZOOM_LOC_WIDTH, y * ZOOM_LOC_HEIGHT ); // BUGHERE : hit building of same nation? if( attackDamage == 0) return; Unit *virtualUnit = NULL, *parentUnit; if(unit_array.is_deleted(parent_recno)) { parentUnit = NULL; //### begin alex 26/9 ###// if(nation_array.is_deleted(nation_recno)) return; //#### end alex 26/9 ####// for(int i=unit_array.size(); i>0; i--) { if(unit_array.is_deleted(i)) continue; virtualUnit = unit_array[i]; break; } if(!virtualUnit) return; //**** BUGHERE } else virtualUnit = parentUnit = unit_array[parent_recno]; virtualUnit->hit_building(parentUnit, target_x_loc, target_y_loc, attackDamage); // ####### end Gilbert 14/5 ########// }
// --------- begin of function BulletHoming::init --------// void BulletHoming::init(char parentType, short parentRecno, short targetXLoc, short targetYLoc, char targetMobileType) { Bullet::init(parentType, parentRecno, targetXLoc, targetYLoc, targetMobileType); // ------- find the maximum range --------// //**** BUGHERE, using parentType and parentRecno to allow bullet by firm, town, etc. //**** BUGHERE, only allow bullet by unit for this version err_when(parent_type!=BULLET_BY_UNIT); Unit *parentUnit = unit_array[parentRecno]; //---------- copy attack info from the parent unit --------// AttackInfo* attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack; speed = attackInfo->bullet_speed; max_step = char((attackInfo->attack_range * ZOOM_LOC_WIDTH + speed-1)/ speed); //--------- keep backup of centre of the bullet ---------// SpriteFrame *spriteFrame = cur_sprite_frame(); // origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap // origin_x += spriteFrame->offset_x + spriteFrame->width/2; origin_y += spriteFrame->offset_y + spriteFrame->height/2; origin2_x = origin_x; origin2_y = origin_y; go_x += spriteFrame->offset_x + spriteFrame->width/2; go_y += spriteFrame->offset_y + spriteFrame->height/2; // ------- find the target_type and target_recno ------// Location *locPtr = world.get_loc(targetXLoc, targetYLoc); //### begin alex 16/5 ###// //if( locPtr->has_unit(mobile_type) ) if(locPtr->has_unit(targetMobileType)) { target_type = BULLET_TARGET_UNIT; //target_recno = locPtr->unit_recno(mobile_type); target_recno = locPtr->unit_recno(targetMobileType); } //#### end alex 16/5 ####// else if( locPtr->is_town() ) { target_type = BULLET_TARGET_TOWN; target_recno = locPtr->town_recno(); } else if( locPtr->is_firm() ) { target_type = BULLET_TARGET_FIRM; target_recno = locPtr->firm_recno(); } else if( locPtr->is_wall() ) { target_type = BULLET_TARGET_WALL; } }
//------- Begin of function FirmMonster::think_attack_neighbor -------// // int FirmMonster::think_attack_neighbor() { //-- don't attack new target if some mobile monsters are already attacking somebody --// if( patrol_unit_count > 0 ) return 0; //-------- only attack if we have enough generals ---------// int generalCount=0; MonsterInFirm* monsterInFirm = monster_general_array; int totalCombatLevel=0; //--- count the number of generals commanding at least 5 soldiers ---// int i; for( i=0 ; i<monster_general_count ; i++, monsterInFirm++ ) { if( monsterInFirm->soldier_count >= 5 ) generalCount++; } if( generalCount<=1 ) // don't attack if there is only one general in the firm return 0; //------ look for neighbors to attack ------// int xOffset, yOffset; int xLoc, yLoc; int attackFlag=0; FirmInfo* firmInfo = firm_res[firm_id]; Location* locPtr; int scanLocWidth = MONSTER_ATTACK_NEIGHBOR_RANGE*2; int scanLocHeight = MONSTER_ATTACK_NEIGHBOR_RANGE*2; int scanLimit = scanLocWidth * scanLocHeight; short targetNation; for(i=firmInfo->loc_width*firmInfo->loc_height+1; i<=scanLimit; i++) { m.cal_move_around_a_point(i, scanLocWidth, scanLocHeight, xOffset, yOffset); xLoc = center_x + xOffset; yLoc = center_y + 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->is_firm()) { Firm *firmPtr = firm_array[locPtr->firm_recno()]; if(firmPtr->nation_recno) { targetNation = firmPtr->nation_recno; attackFlag = 1; xLoc = firmPtr->loc_x1; yLoc = firmPtr->loc_y1; break; } } else if(locPtr->is_town()) { Town *townPtr = town_array[locPtr->town_recno()]; if(townPtr->nation_recno) { targetNation = townPtr->nation_recno; attackFlag = 1; xLoc = townPtr->loc_x1; yLoc = townPtr->loc_y1; break; } } } if( !attackFlag ) return 0; //------- attack the civilian now --------// current_monster_action_mode = MONSTER_ACTION_ATTACK; mobilize_general( m.random(monster_general_count)+1 ); if( patrol_unit_count > 0 ) { //### begin alex 16/9 ###// set_hostile_nation(targetNation); //#### end alex 16/9 ####// // ##### patch begin Gilbert 5/8 #######// unit_array.attack(xLoc, yLoc, 0, patrol_unit_array, patrol_unit_count, COMMAND_AI, 0); // ##### patch end Gilbert 5/8 #######// return 1; } else return 0; }
//------- Begin of function Tornado::hit_building -----// // building means firm or town // void Tornado::hit_building() { short damageXLoc = damage_x_loc(); short damageYLoc = damage_y_loc(); if( damageXLoc < 0 || damageXLoc >= world.max_x_loc || damageYLoc < 0 || damageYLoc >= world.max_y_loc) return; Location* locPtr = world.get_loc(damageXLoc, damageYLoc); if(locPtr->is_firm() ) // && firm_res[(firmPtr=firm_array[locPtr->firm_recno()])->firm_id]->buildable ) { Firm *firmPtr = firm_array[locPtr->firm_recno()]; firmPtr->hit_points -= attack_damage*2; if( !damage_player_flag && firmPtr->is_own() ) { damage_player_flag = 1; // add news message news_array.tornado_hit(sprite_recno); } if( firmPtr->hit_points <= 0) { firmPtr->hit_points = (float) 0; se_res.sound(firmPtr->center_x, firmPtr->center_y, 1, 'F', firmPtr->firm_id, "DIE" ); firm_array.del_firm(locPtr->firm_recno()); } } if( locPtr->is_town() ) { Town *townPtr = town_array[locPtr->town_recno()]; if( !damage_player_flag && townPtr->is_own() ) { damage_player_flag = 1; // add news message news_array.tornado_hit(sprite_recno); } if( townPtr->hit_points > 0.0f ) { townPtr->hit_points -= attack_damage*2; if( townPtr->hit_points <= 0 ) { townPtr->hit_points = (float) 0; } } else { // ###### begin Gilbert 10/2 #######// if( (life_time % 10) == 0 ) townPtr->kill_town_people(0); // ###### end Gilbert 10/2 #######// } } }
//--------- Begin of function Nation::ai_assign_spy --------// // // Try to locate an existing spy for use. // // <int> targetXLoc, targetYLoc - the target location // [int] spyRaceId - if specified, only spies of this race // will be located. (default:0) // [int] mobileOnly - get mobile spies only. (default:0) // int Nation::ai_assign_spy(int targetXLoc, int targetYLoc, int spyRaceId, int mobileOnly) { int unitRecno=0; //---- try to find an existing spy ----// Spy* spyPtr = ai_find_spy( targetXLoc, targetYLoc, spyRaceId, mobileOnly ); if( spyPtr ) unitRecno = spyPtr->mobilize_spy(); //--- if not successful, then try to hire one ---// if( !unitRecno ) unitRecno = hire_unit(SKILL_SPYING, spyRaceId, targetXLoc, targetYLoc); //--- if cannot hire one, try to train one ----// int trainTownRecno=0; if( !unitRecno ) unitRecno = train_unit(SKILL_SPYING, spyRaceId, targetXLoc, targetYLoc, trainTownRecno); if( !unitRecno ) return 0; //------ get the spy object of the unit ------// Unit* unitPtr = unit_array[unitRecno]; err_when( !unitPtr->spy_recno ); spyPtr = spy_array[unitPtr->spy_recno]; //------- get the nation of the assign destination -----// Location* locPtr = world.get_loc(targetXLoc, targetYLoc); int cloakedNationRecno; if( locPtr->is_firm() ) { Firm* firmPtr = firm_array[locPtr->firm_recno()]; err_when( firmPtr->nation_recno==0 ); // cannot assign to a monster firm cloakedNationRecno = firmPtr->nation_recno; } else if( locPtr->is_town() ) { Town* townPtr = town_array[locPtr->town_recno()]; cloakedNationRecno = townPtr->nation_recno; } else { return 0; // the original firm or town has been destroyed or sold } //------- Add the assign spy action --------// int actionRecno = add_action( targetXLoc, targetYLoc, -1, -1, ACTION_AI_ASSIGN_SPY, cloakedNationRecno, 1, unitRecno ); if( !actionRecno ) return 0; //------ if the unit is under training ------// if( trainTownRecno ) town_array[trainTownRecno]->train_unit_action_id = get_action(actionRecno)->action_id; return 1; }
// ----- begin of function ScenarioEditor::detect_human_view ------// // int ScenarioEditor::detect_human_view() { if( power.command_id ) return 0; // detect map area if( mouse.double_click( ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, 0 ) ) // left click { int xLoc, yLoc; if( world.zoom_matrix->get_detect_location(mouse.click_x(0), mouse.click_y(0), &xLoc, &yLoc, NULL) ) { if( unit_or_struct == 0 && !vbrowse_unit_id.none_record ) { // put unit human_unit_id_array[human_unit_id_browse_recno-1] // on (xLoc, yLoc) int unitId = human_unit_id_array[human_unit_id_browse_recno-1]; UnitInfo *unitInfo = unit_res[unitId]; SpriteInfo *spriteInfo = sprite_res[unitInfo->sprite_id]; if( world.check_unit_space(xLoc, yLoc, xLoc+spriteInfo->loc_width-1, yLoc+spriteInfo->loc_height-1, unitInfo->mobile_type) ) { int unitRecno = unit_array.add_unit( unitId, brush_player_recno, RANK_SOLDIER, 100, xLoc, yLoc ); if( unitRecno && unitId == UNIT_WAGON ) { err_when( !human_race_filter ); UnitWagon* unitPtr = (UnitWagon *)unit_array[unitRecno]; unitPtr->race_id = human_race_filter; unitPtr->set_pop( MAX_WAGON_POPULATION ); } } } else if( unit_or_struct == 1 && !vbrowse_firm_build.none_record ) { err_when( human_firm_group_array[human_firm_group_browse_recno] == 0 ); if( human_firm_group_array[human_firm_group_browse_recno-1] < 0 ) { // put town of race -human_firm_group_array[human_firm_group_browse_recno] // (xLoc, yLoc) if( world.can_build_town(xLoc, yLoc, 0) ) { int raceId = -human_firm_group_array[human_firm_group_browse_recno-1]; int townRecno = town_array.generate_town(brush_player_recno, raceId, xLoc, yLoc); if( townRecno ) { Town *townPtr = town_array[townRecno]; townPtr->construction_completion_percent = 100; townPtr->under_construction = 0; // init_pop if( brush_player_recno ) townPtr->init_pop( 0, 100, 0, 1 ); else townPtr->init_pop( 0, town_array.independent_town_resistance(), 0, 1 ); townPtr->auto_set_layout(); } } } else { // put firm group human_firm_group_array[human_firm_group_browse_recno-1] // on (xLoc, yLoc) FirmGroup *firmGroup = firm_res.get_group(human_firm_group_array[human_firm_group_browse_recno-1]); if( world.can_build_firm( xLoc, yLoc, firmGroup->firm_id, 0) ) { if (brush_player_recno == 0) { box.msg( text_editor.str_no_independent() ); // "Cannot add any Independent structures" ); } else { if( firmGroup->firm_id == FIRM_BASE ) // if it's a seat of power, give the nation a scroll of power first god_res[firmGroup->race_id]->enable_know(brush_player_recno); firm_array.generate_firm( xLoc, yLoc, brush_player_recno, firmGroup->firm_id, firmGroup->race_code ); } } } } } return 1; } if( mouse.double_click( ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, 1) ) // right click to remove { int xLoc, yLoc; char mobileType; Location* locPtr = power.test_detect(mouse.click_x(1), mouse.click_y(1), &mobileType, &xLoc, &yLoc ); if( locPtr ) { if( locPtr->unit_recno(mobileType) ) // remove unit { int unitRecno = locPtr->unit_recno(mobileType); if( !unit_array.is_deleted(unitRecno) ) { unit_array[unitRecno]->hit_points = 0.0f; } } else if( locPtr->is_firm() ) // remove firm { int firmRecno = locPtr->firm_recno(); if( !firm_array.is_deleted(firmRecno) ) { firm_array.del_firm( firmRecno ); } } else if( locPtr->is_town() ) // remove town { int townRecno = locPtr->town_recno(); if( !town_array.is_deleted(townRecno) ) { town_array.del_town(townRecno); } } } return 1; } return 0; }
//----------- Begin of function Nation::find_best_place_loc ----------// // // Determine the location of a new firm. It's best to have the // new firm within the refective range of: towns, factories and // mines. // // <short> buildFirmId - >0 id. of the firm to be built // 0 if the place to be built is a town // <short> refXLoc, refYLoc - either the location of a town or a firm, // the market must be built next to it. // <short&> resultXLoc, resultYLoc - result location of the firm. // [short] distance - the distance between the given place and // new place. // // return: <int> 1 - succeed, 0 - fail // int Nation::find_best_place_loc(short buildFirmId, short refXLoc, short refYLoc, short& resultXLoc, short& resultYLoc, short distance) { #define IDEAL_INTER_PLACE_SPACE 3 if (distance == 0) distance = IDEAL_INTER_PLACE_SPACE; Location *locPtr = world.get_loc(refXLoc, refYLoc); short centerX, centerY, refX1, refY1, refX2, refY2; //-------- get the refective area ---------// int originFirmRecno=0, originTownRecno=0; Firm* firmPtr; Town* townPtr; BYTE buildRegionId = locPtr->region_id; int buildIsPlateau = locPtr->is_plateau(); int effectiveDis; //-----------------------------------------// if( locPtr->is_firm() ) { originFirmRecno = locPtr->firm_recno(); firmPtr = firm_array[originFirmRecno]; centerX = firmPtr->center_x; centerY = firmPtr->center_y; effectiveDis = world.effective_distance(buildFirmId, firmPtr->firm_id); // if( firmPtr->firm_id == FIRM_HARBOR ) // { // buildRegionId = ((FirmHarbor*)firmPtr)->land_region_id; // buildIsPlateau = 0; // } } else if( locPtr->is_town() ) { originTownRecno = locPtr->town_recno(); townPtr = town_array[originTownRecno]; centerX = townPtr->center_x; centerY = townPtr->center_y; effectiveDis = world.effective_distance(buildFirmId, 0); } else err_here(); refX1 = centerX - effectiveDis; refY1 = centerY - effectiveDis; refX2 = centerX + effectiveDis; refY2 = centerY + effectiveDis; //------------------------------------------------------// int placeLocWidth, placeLocHeight; if( buildFirmId ) { placeLocWidth = firm_res[buildFirmId]->loc_width; placeLocHeight = firm_res[buildFirmId]->loc_height; } else { placeLocWidth = STD_TOWN_LOC_WIDTH; placeLocHeight = STD_TOWN_LOC_HEIGHT; } refX1 -= placeLocWidth/2; // since we use loc_x1 as the building reference, we need to shift it so it will match the use of center_x in effective distance refY1 -= placeLocHeight/2; refX1 = max(0, refX1); refY1 = max(0, refY1); refX2 = min(MAX_WORLD_X_LOC-1, refX2); refY2 = min(MAX_WORLD_Y_LOC-1, refY2); //-------- build a matrix on the refective area ---------// int refWidth=refX2-refX1+1, refHeight=refY2-refY1+1; short* refMatrix = (short*) mem_add( sizeof(short) * refWidth * refHeight ); short* refMatrixPtr; //------ initialize the weights of the matrix ------// int xLoc, yLoc; // inner locations in the matrix receives more weights than outer locations do int t1, t2; for( yLoc=refY1 ; yLoc<=refY2 ; yLoc++ ) { refMatrixPtr = refMatrix + (yLoc-refY1)*refWidth; locPtr = world.get_loc( refX1, yLoc ); for( xLoc=refX1 ; xLoc<=refX2 ; xLoc++, refMatrixPtr++, locPtr++ ) { t1 = abs(xLoc-centerX); t2 = abs(yLoc-centerY); if( locPtr->region_id != buildRegionId || locPtr->is_plateau() != buildIsPlateau || locPtr->is_power_off() ) { *refMatrixPtr = -1000; } else { *refMatrixPtr = 10-max(t1, t2); // it's negative value, and the value is lower for the outer ones } } } //----- calculate weights of the locations in the matrix ----// int xLocB, yLocB, weightAdd, weightReduce; short refBX1, refBY1, refBX2, refBY2; short refCX1, refCY1, refCX2, refCY2; for( yLoc=refY1 ; yLoc<=refY2 ; yLoc++ ) { locPtr = world.get_loc(refX1, yLoc); for( xLoc=refX1 ; xLoc<=refX2 ; xLoc++, locPtr++ ) { if( locPtr->region_id != buildRegionId || locPtr->is_plateau() != buildIsPlateau || locPtr->is_power_off() ) { continue; } //------- if there is a firm on the location ------// weightAdd = 0; weightReduce = 0; if( locPtr->is_firm() ) { firmPtr = firm_array[locPtr->firm_recno()]; if( buildFirmId==FIRM_MARKET || buildFirmId==FIRM_FACTORY ) // only factories & market places need building close to other firms { int rc = 1; if( firmPtr->nation_recno != nation_recno ) rc = 0; //----- check if the firm is of the right type ----// if( buildFirmId==FIRM_MARKET ) // build a market place close to mines and factories { if( firmPtr->firm_id!=FIRM_MINE && firmPtr->firm_id!=FIRM_FACTORY ) // market places should be built close to factories and mines and they are the only two firms that influence the location of the market place rc = 0; } else if( buildFirmId==FIRM_FACTORY ) // build a factory close to mines and market places { if( firmPtr->firm_id!=FIRM_MINE && firmPtr->firm_id!=FIRM_MARKET ) // market places should be built close to factories and mines and they are the only two firms that influence the location of the market place rc = 0; } //------------------------------------------/ if( rc ) { effectiveDis = world.effective_distance(firmPtr->firm_id, buildFirmId); refBX1 = firmPtr->center_x - effectiveDis; refBY1 = firmPtr->center_y - effectiveDis; refBX2 = firmPtr->center_x + effectiveDis; refBY2 = firmPtr->center_y + effectiveDis; weightAdd = 40; } } refCX1 = firmPtr->loc_x1-distance ; // add negative weights on space around this firm refCY1 = firmPtr->loc_y1-distance ; // so to prevent firms from building right next to the firm refCX2 = firmPtr->loc_x2+distance ; // and leave some space for walking path. refCY2 = firmPtr->loc_y2+distance ; weightReduce = 20; } //------- if there is a town on the location ------// else if( locPtr->is_town() ) { townPtr = town_array[locPtr->town_recno()]; effectiveDis = world.effective_distance(0, buildFirmId); refBX1 = townPtr->center_x - effectiveDis; refBY1 = townPtr->center_y - effectiveDis; refBX2 = townPtr->center_x + effectiveDis; refBY2 = townPtr->center_y + effectiveDis; weightAdd = townPtr->population*2; //----- if the town is not our own -----// if(townPtr->nation_recno != nation_recno) { if( townPtr->nation_recno==0 ) // it's an independent town weightAdd = weightAdd * ( 100-(int)townPtr->resistance(nation_recno) ) / 100; else // more friendly nations get higher weights { int relationStatus = get_relation_status(townPtr->nation_recno); if( relationStatus >= RELATION_NEUTRAL ) weightAdd = weightAdd * (relationStatus-RELATION_NEUTRAL+1) / 4; } } refCX1 = townPtr->loc_x1-distance ; // add negative weights on space around this firm refCY1 = townPtr->loc_y1-distance ; // so to prevent firms from building right next to the firm refCX2 = townPtr->loc_x2+distance ; // and leave some space for walking path. refCY2 = townPtr->loc_y2+distance ; weightReduce = 100; } else continue; //------ add weights to the matrix ------// if( weightAdd ) { for( yLocB=max(refY1,refBY1) ; yLocB<=min(refY2,refBY2) ; yLocB++ ) { xLocB = max(refX1,refBX1); refMatrixPtr = refMatrix + (yLocB-refY1)*refWidth + (xLocB-refX1); for( ; xLocB<=min(refX2,refBX2) ; xLocB++ ) { *refMatrixPtr++ += weightAdd; } } } //------ reduce weights from the matrix ------// if( weightReduce ) { for( yLocB=max(refY1,refCY1) ; yLocB<=min(refY2,refCY2) ; yLocB++ ) { xLocB = max(refX1,refCX1); refMatrixPtr = refMatrix + (yLocB-refY1)*refWidth + (xLocB-refX1); for( ; xLocB<=min(refX2,refCX2) ; xLocB++ ) { *refMatrixPtr++ -= weightReduce; } } } } } //------ select the best building site in the matrix -------// resultXLoc = -1; resultYLoc = -1; short thisWeight, bestWeight=0; refX2 -= placeLocWidth-1; // do not scan beyond the border refY2 -= placeLocHeight-1; for( yLoc=refY1 ; yLoc<=refY2 ; yLoc++ ) { for( xLoc=refX1 ; xLoc<=refX2 ; xLoc++ ) { if( world.get_region_id(xLoc, yLoc) != buildRegionId ) continue; if( buildFirmId ) { if( !world.can_build_firm(xLoc, yLoc, buildFirmId) ) continue; } else { if( !world.can_build_town(xLoc, yLoc) ) continue; } //---- calculate the average weight of a firm area ----// int totalWeight=0; refMatrixPtr = refMatrix + (yLoc-refY1)*refWidth + (xLoc-refX1); for( int yCount=0 ; yCount<placeLocHeight ; yCount++ ) { for( int xCount=0 ; xCount<placeLocWidth ; xCount++ ) { totalWeight += *refMatrixPtr++; } refMatrixPtr += refWidth-placeLocWidth; } //------- compare the weights --------// thisWeight = totalWeight / (placeLocWidth*placeLocHeight); if( thisWeight > bestWeight ) { bestWeight = thisWeight; resultXLoc = xLoc; resultYLoc = yLoc; } } } //------ release the refective matrix -----// mem_del( refMatrix ); return resultXLoc >= 0; }
//--------- Begin of function UnitMonster::random_attack --------// // // Randomly pick an object to attack. // int UnitMonster::random_attack() { #define ATTACK_SCAN_RANGE 100 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); int rc; for( int i=2 ; i<ATTACK_SCAN_RANGE*ATTACK_SCAN_RANGE ; i++ ) { m.cal_move_around_a_point(i, ATTACK_SCAN_RANGE, ATTACK_SCAN_RANGE, 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; rc = 0; //----- 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; rc = 1; } //----- if there is a firm on the location ------// if( !rc && locPtr->is_firm() ) { int firmRecno = locPtr->firm_recno(); if( firm_array.is_deleted(firmRecno) ) continue; rc = 1; } //----- if there is a town on the location ------// if( !rc && locPtr->is_town() ) { int townRecno = locPtr->town_recno(); if( town_array.is_deleted(townRecno) ) continue; rc = 1; } //-------------------------------------// if( rc ) { group_order_monster(xLoc, yLoc, 1); // 1-the action is attack return 1; } } return 0; }
//----------- Begin of function Unit::resume_original_attack_action -------// // void Unit::resume_original_attack_action() { if( !original_action_mode ) return; if( original_action_mode != ACTION_ATTACK_UNIT && original_action_mode != ACTION_ATTACK_FIRM && original_action_mode != ACTION_ATTACK_TOWN ) { original_action_mode = 0; return; } //--------------------------------------------// err_when( original_action_x_loc<0 || original_action_x_loc>=MAX_WORLD_X_LOC ); err_when( original_action_y_loc<0 || original_action_y_loc>=MAX_WORLD_Y_LOC ); Location* locPtr = world.get_loc(original_action_x_loc, original_action_y_loc); int targetNationRecno = -1; if( original_action_mode == ACTION_ATTACK_UNIT && locPtr->has_unit(UNIT_LAND) ) { int unitRecno = locPtr->unit_recno(UNIT_LAND); if( unitRecno == original_action_para ) targetNationRecno = unit_array[unitRecno]->nation_recno; } else if( original_action_mode == ACTION_ATTACK_FIRM && locPtr->is_firm() ) { int firmRecno = locPtr->firm_recno(); if( firmRecno == original_action_para ) targetNationRecno = firm_array[firmRecno]->nation_recno; } else if( original_action_mode == ACTION_ATTACK_TOWN && locPtr->is_town() ) { int townRecno = locPtr->town_recno(); if( townRecno == original_action_para ) targetNationRecno = town_array[townRecno]->nation_recno; } //----- the original target is no longer valid ----// if( targetNationRecno == -1 ) { original_action_mode = 0; return; } //---- only resume attacking the target if the target nation is at war with us currently ---// if( !targetNationRecno || (targetNationRecno && targetNationRecno != nation_recno && nation_array[nation_recno]->get_relation_status(targetNationRecno) == NATION_HOSTILE )) { short selectedArray[1]; selectedArray[0] = sprite_recno; // use unit_array.attack() instead of unit.attack_???() as we are unsure about what type of object the target is. // #### begin Gilbert 5/8 ########// unit_array.attack(original_action_x_loc, original_action_y_loc, 0, selectedArray, 1, COMMAND_AI, 0 ); // #### end Gilbert 5/8 ########// } original_action_mode = 0; }
void Unit::resume_original_action() { if( !original_action_mode ) return; //--------- If it is an attack action ---------// if( original_action_mode == ACTION_ATTACK_UNIT || original_action_mode == ACTION_ATTACK_FIRM || original_action_mode == ACTION_ATTACK_TOWN ) { resume_original_attack_action(); return; } //--------------------------------------------// if( original_action_x_loc<0 || original_action_x_loc>=MAX_WORLD_X_LOC || original_action_y_loc<0 || original_action_y_loc>=MAX_WORLD_Y_LOC ) { original_action_mode = 0; return; } short selectedArray[1]; selectedArray[0] = sprite_recno; // use unit_array.attack() instead of unit.attack_???() as we are unsure about what type of object the target is. Location* locPtr = world.get_loc(original_action_x_loc, original_action_y_loc); //--------- resume assign to town -----------// if( original_action_mode == ACTION_ASSIGN_TO_TOWN && locPtr->is_town() ) { if( locPtr->town_recno() == original_action_para && town_array[original_action_para]->nation_recno == nation_recno ) { unit_array.assign( original_action_x_loc, original_action_y_loc, 0, COMMAND_AUTO, selectedArray, 1 ); } } //--------- resume assign to firm ----------// else if( original_action_mode == ACTION_ASSIGN_TO_FIRM && locPtr->is_firm() ) { if( locPtr->firm_recno() == original_action_para && firm_array[original_action_para]->nation_recno == nation_recno ) { unit_array.assign( original_action_x_loc, original_action_y_loc, 0, COMMAND_AUTO, selectedArray, 1 ); } } //--------- resume build firm ---------// else if( original_action_mode == ACTION_BUILD_FIRM ) { if( world.can_build_firm( original_action_x_loc, original_action_y_loc, original_action_para, sprite_recno ) ) { build_firm( original_action_x_loc, original_action_y_loc, original_action_para, COMMAND_AUTO ); } } //--------- resume settle ---------// else if( original_action_mode == ACTION_SETTLE ) { if( world.can_build_town( original_action_x_loc, original_action_y_loc, sprite_recno ) ) { unit_array.settle( original_action_x_loc, original_action_y_loc, 0, COMMAND_AUTO, selectedArray, 1 ); } } //--------- resume move ----------// else if( original_action_mode == ACTION_MOVE ) { unit_array.move_to( original_action_x_loc, original_action_y_loc, 0, selectedArray, 1, COMMAND_AUTO ); } original_action_mode = 0; }
//--------- Begin of function SiteArray::next_day ----------// // void SiteArray::next_day() { if( info.game_date%30 == 0 ) { generate_raw_site(); // check if we need to generate existing raw sites are being used up and if we need to generate new ones } //-- if there is any scroll or gold coins available, ask AI to get them --// // #### begin Gilbert 3/11 ######// if(scroll_count || gold_coin_count || item_count || weapon_blueprint_count ) // #### end Gilbert 3/11 ######// { int aiGetSiteObject = (info.game_date%5 == 0); Site* sitePtr; Location *locPtr; for(int i=size(); i; i--) { if(is_deleted(i)) continue; sitePtr = site_array[i]; switch(sitePtr->site_type) { case SITE_SCROLL: case SITE_GOLD_COIN: case SITE_ITEM: case SITE_WEAPON_BLUEPRINT: locPtr = world.get_loc(sitePtr->map_x_loc, sitePtr->map_y_loc); //---- if the unit is standing on a scroll site -----// if(locPtr->unit_recno(UNIT_LAND)) { // ####### begin Gilbert 25/5 ##########// int unitRecno = locPtr->unit_recno(UNIT_LAND); if( !unit_array.is_deleted(unitRecno) ) sitePtr->get_site_object( unitRecno ); // ####### end Gilbert 25/5 ##########// } else if(aiGetSiteObject) { sitePtr->ai_get_site_object(); } break; } } } //-------- debug testing --------// #ifdef DEBUG if( info.game_date%10 == 0 ) { Site* sitePtr; Location* locPtr; for( int i=1 ; i<=size() ; i++ ) { if( site_array.is_deleted(i) ) continue; sitePtr = site_array[i]; locPtr = world.get_loc( sitePtr->map_x_loc, sitePtr->map_y_loc ); err_when( !locPtr->has_site() ); err_when( locPtr->site_recno() != i ); if( sitePtr->has_mine ) { err_when( !locPtr->is_firm() ); err_when( firm_array[locPtr->firm_recno()]->firm_id != FIRM_MINE && firm_array[locPtr->firm_recno()]->firm_id != FIRM_ALCHEMY ); } else { // disable because a mine can be upon more than one mine // err_when( locPtr->is_firm() || locPtr->is_town() ); } } } #endif }
//------- Begin of function Town::think_attack_nearby_enemy -------// // // Think about attacking enemies near the town. // int Town::think_attack_nearby_enemy() { enum { SCAN_X_RANGE = 6, SCAN_Y_RANGE = 6 }; int xLoc1 = loc_x1 - SCAN_X_RANGE; int yLoc1 = loc_y1 - SCAN_Y_RANGE; int xLoc2 = loc_x2 + SCAN_X_RANGE; int yLoc2 = loc_y2 + SCAN_Y_RANGE; xLoc1 = max( xLoc1, 0 ); yLoc1 = max( yLoc1, 0 ); xLoc2 = min( xLoc2, MAX_WORLD_X_LOC-1 ); yLoc2 = min( yLoc2, MAX_WORLD_Y_LOC-1 ); //------------------------------------------// int enemyCombatLevel=0; // the higher the rating, the easier we can attack the target town. int xLoc, yLoc; int enemyXLoc= -1, enemyYLoc; Unit* unitPtr; Nation* nationPtr = nation_array[nation_recno]; Firm* firmPtr; Location* locPtr; for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { locPtr = world.get_loc(xLoc1, yLoc); for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ ) { //--- if there is an enemy unit here ---// if( locPtr->has_unit(UNIT_LAND) ) { unitPtr = unit_array[ locPtr->unit_recno(UNIT_LAND) ]; if( !unitPtr->nation_recno ) continue; //--- if the unit is idle and he is our enemy ---// if( unitPtr->cur_action == SPRITE_IDLE && nationPtr->get_relation_status(unitPtr->nation_recno) == NATION_HOSTILE ) { err_when( unitPtr->nation_recno == nation_recno ); enemyCombatLevel += (int) unitPtr->hit_points; if( enemyXLoc == -1 || m.random(5)==0 ) { enemyXLoc = xLoc; enemyYLoc = yLoc; } } } //--- if there is an enemy firm here ---// else if( locPtr->is_firm() ) { firmPtr = firm_array[locPtr->firm_recno()]; //------- if this is a monster firm ------// if( firmPtr->firm_id == FIRM_MONSTER ) // don't attack monster here, OAI_MONS.CPP will handle that continue; //------- if this is a firm of our enemy -------// if( nationPtr->get_relation_status(firmPtr->nation_recno) == NATION_HOSTILE ) { err_when( firmPtr->nation_recno == nation_recno ); if( firmPtr->worker_count == 0 ) enemyCombatLevel += 50; // empty firm else { Worker* workerPtr = firmPtr->worker_array; for( int i=firmPtr->worker_count ; i>0 ; i--, workerPtr++ ) enemyCombatLevel += workerPtr->hit_points; } if( enemyXLoc == -1 || m.random(5)==0 ) { enemyXLoc = firmPtr->loc_x1; enemyYLoc = firmPtr->loc_y1; } } } } } //--------- attack the target now -----------// if( enemyCombatLevel > 0 ) { err_when( enemyXLoc < 0 ); nationPtr->ai_attack_target( enemyXLoc, enemyYLoc, enemyCombatLevel ); return 1; } return 0; }
//--------- Begin of function Bullet::check_hit -------// // check if the bullet hit a target // return true if hit int Bullet::check_hit() { err_when(SCAN_RANGE != 5); short x,y; short townHit[SCAN_RANGE*SCAN_RANGE]; short firmHit[SCAN_RANGE*SCAN_RANGE]; int hitCount = 0; int townHitCount = 0; int firmHitCount = 0; for( int c = 0; c < SCAN_RANGE*SCAN_RANGE; ++c ) { x = target_x_loc + spiral_x[c]; y = target_y_loc + spiral_y[c]; if( x >= 0 && x < world.max_x_loc && y >= 0 && y < world.max_y_loc ) { Location *locPtr = world.get_loc(x, y); if(target_mobile_type==UNIT_AIR) { if(locPtr->has_unit(UNIT_AIR)) { hit_target(x,y); hitCount++; } } else { if(locPtr->is_firm()) { short firmRecno = locPtr->firm_recno(); // check this firm has not been attacked short *firmHitPtr; for( firmHitPtr = firmHit+firmHitCount-1; firmHitPtr >= firmHit; --firmHitPtr ) { if( *firmHitPtr == firmRecno ) break; } if( firmHitPtr < firmHit ) // not found { firmHit[firmHitCount++] = firmRecno; hit_building(x,y); hitCount++; } } else if( locPtr->is_town() ) { short townRecno = locPtr->town_recno(); // check this town has not been attacked short *townHitPtr; for( townHitPtr = townHit+townHitCount-1; townHitPtr >= townHit; --townHitPtr ) { if( *townHitPtr == townRecno ) break; } if( townHitPtr < townHit ) // not found { townHit[townHitCount++] = townRecno; hit_building(x,y); hitCount++; } } else if(locPtr->is_wall()) { hit_wall(x,y); hitCount++; } else { hit_target(x,y); // note: no error checking here because mobile_type should be taken into account hitCount++; } } } } return hitCount; }
//--------- Begin of function SiteArray::next_day ----------// // void SiteArray::next_day() { if( info.game_date%30 == 0 ) { generate_raw_site(); // check if we need to generate existing raw sites are being used up and if we need to generate new ones } //-- if there is any scroll or gold coins available, ask AI to get them --// if(scroll_count || gold_coin_count) { int aiGetSiteObject = (info.game_date%5 == 0); Site* sitePtr; Location *locPtr; for(int i=size(); i; i--) { if(is_deleted(i)) continue; sitePtr = site_array[i]; switch(sitePtr->site_type) { case SITE_SCROLL: case SITE_GOLD_COIN: locPtr = world.get_loc(sitePtr->map_x_loc, sitePtr->map_y_loc); //---- if the unit is standing on a scroll site -----// if(locPtr->has_unit(UNIT_LAND)) { sitePtr->get_site_object( locPtr->unit_recno(UNIT_LAND) ); } else if(aiGetSiteObject) { sitePtr->ai_get_site_object(); } break; } } } //-------- debug testing --------// #ifdef DEBUG if( info.game_date%10 == 0 ) { Site* sitePtr; Location* locPtr; for( int i=1 ; i<=size() ; i++ ) { if( site_array.is_deleted(i) ) continue; sitePtr = site_array[i]; locPtr = world.get_loc( sitePtr->map_x_loc, sitePtr->map_y_loc ); err_when( !locPtr->has_site() ); err_when( locPtr->site_recno() != i ); if( sitePtr->has_mine ) { err_when( !locPtr->is_firm() ); err_when( firm_array[locPtr->firm_recno()]->firm_id != FIRM_MINE ); } else { err_when( locPtr->is_firm() || locPtr->is_town() ); } } } #endif }
// ----- begin of function ScenarioEditor::detect_monster_view ------// // int ScenarioEditor::detect_monster_view() { if( power.command_id ) return 0; // detect map area if( mouse.double_click( ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, 0 ) ) // left click { int xLoc, yLoc; if( world.zoom_matrix->get_detect_location(mouse.click_x(0), mouse.click_y(0), &xLoc, &yLoc, NULL) ) { if( unit_or_struct == 0 && !vbrowse_unit_id.none_record ) { // put unit monster_unit_id_array[monster_unit_id_browse_recno-1] // on (xLoc, yLoc) int unitId = monster_unit_id_array[monster_unit_id_browse_recno-1]; UnitInfo *unitInfo = unit_res[unitId]; SpriteInfo *spriteInfo = sprite_res[unitInfo->sprite_id]; if( world.check_unit_space(xLoc, yLoc, xLoc+spriteInfo->loc_width-1, yLoc+spriteInfo->loc_height-1, unitInfo->mobile_type) ) { unit_array.add_unit( unitId, brush_player_recno, RANK_SOLDIER, 100, xLoc, yLoc ); } } else if( unit_or_struct == 1 && !vbrowse_firm_build.none_record ) { err_when( monster_firm_group_array[monster_firm_group_browse_recno-1] == 0 ); // put firm group monster_firm_group_array[monster_firm_group_browse_recno] // on (xLoc, yLoc) FirmGroup *firmGroup = firm_res.get_group(monster_firm_group_array[monster_firm_group_browse_recno-1]); if( world.can_build_firm( xLoc, yLoc, firmGroup->firm_id, 0) ) { if( brush_player_recno && nation_array[brush_player_recno]->is_human() && firm_res[firmGroup->firm_id]->setup_live_points_cost > 0 ) { box.msg( text_editor.str_no_human() ); // "Human Kingdom cannot possess Fryhtan structure" ); } else if (brush_player_recno == 0 && firmGroup->firm_id != FIRM_LAIR) { box.msg( text_editor.str_no_independent() ); // "Cannot add any Independent structures" ); } else { firm_array.generate_firm( xLoc, yLoc, brush_player_recno, firmGroup->firm_id, firmGroup->race_code ); } } } } return 1; } // ------ remove object -------// if( mouse.double_click( ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, 1) ) // right click to remove { int xLoc, yLoc; char mobileType; Location* locPtr = power.test_detect(mouse.click_x(1), mouse.click_y(1), &mobileType, &xLoc, &yLoc ); if( locPtr ) { if( locPtr->unit_recno(mobileType) ) // remove unit { int unitRecno = locPtr->unit_recno(mobileType); if( !unit_array.is_deleted(unitRecno) ) unit_array[unitRecno]->hit_points = 0.0f; } else if( locPtr->is_firm() ) // remove firm { int firmRecno = locPtr->firm_recno(); if( !firm_array.is_deleted(firmRecno) ) { firm_array.del_firm( firmRecno ); } } else if( locPtr->is_town() ) // remove town { int townRecno = locPtr->town_recno(); if( !town_array.is_deleted(townRecno) ) { town_array.del_town(townRecno); } } } return 1; } return 0; }
//--------- Begin of function UnitGod::cast_on_loc ---------// // void UnitGod::cast_on_loc(int castXLoc, int castYLoc) { Location* locPtr = world.get_loc( castXLoc, castYLoc ); //--- if there is any unit on the location ---// if( locPtr->has_unit(UNIT_LAND) ) { cast_on_unit( locPtr->unit_recno(UNIT_LAND), 1 ); } else if( locPtr->has_unit(UNIT_SEA) ) { Unit* unitPtr = unit_array[ locPtr->unit_recno(UNIT_SEA) ]; //-- only heal human units belonging to our nation in ships --// if( unitPtr->nation_recno == nation_recno && unit_res[unitPtr->unit_id]->unit_class == UNIT_CLASS_SHIP ) { UnitMarine* unitMarine = (UnitMarine*) unitPtr; for( int i=0 ; i<unitMarine->unit_count ; i++ ) { int divider = 4; // the size of a ship is 4 locations (2x2) cast_on_unit( unitMarine->unit_recno_array[i], divider ); // the effects are weaken on ship units, only 50% of the original effects } } } //--------- on firms ---------// else if( locPtr->is_firm() ) { Firm* firmPtr = firm_array[ locPtr->firm_recno() ]; int divider = (firmPtr->loc_x2-firmPtr->loc_x1+1) * (firmPtr->loc_y2-firmPtr->loc_y1+1); if( god_id == GOD_ZULU ) divider = 1; // range of zulu god is 1, no need to divide if( firmPtr->overseer_recno ) { cast_on_unit( firmPtr->overseer_recno, divider ); } if( firmPtr->worker_array && firm_res[firmPtr->firm_id]->live_in_town==0 ) { Worker* workerPtr = firmPtr->worker_array; for( int i=0 ; i<firmPtr->worker_count ; i++, workerPtr++ ) { cast_on_worker(workerPtr, firmPtr->nation_recno, divider); } } } //--------- on towns ----------// else if( locPtr->is_town() ) { Town* townPtr = town_array[ locPtr->town_recno() ]; if( god_id == GOD_JAPANESE && townPtr->nation_recno != nation_recno) { int divider = STD_TOWN_LOC_WIDTH * STD_TOWN_LOC_HEIGHT; for( int i=0 ; i<MAX_RACE ; i++ ) { if( townPtr->race_pop_array[i]==0 ) continue; float changePoints = (float)7 + misc.random(8); // decrease 7 to 15 loyalty points instantly if( townPtr->nation_recno ) townPtr->change_loyalty(i+1, -changePoints/divider); else townPtr->change_resistance(i+1, nation_recno, -changePoints/divider); } } else if( god_id == GOD_EGYPTIAN && townPtr->nation_recno == nation_recno) { int headCount; int raceId; for( headCount = 5; headCount > 0 && townPtr->population < MAX_TOWN_GROWTH_POPULATION && (raceId = townPtr->pick_random_race(1,1)); --headCount ) { townPtr->inc_pop(raceId, 0, (int)townPtr->race_loyalty_array[raceId-1]); } } } }