void UnitGroup::exe_attack(int targetObjRecno) { BaseObj *targetObj = base_obj_array[targetObjRecno]; int targetWidth = targetObj->obj_loc_width(); int targetHeight = targetObj->obj_loc_height(); int targetLocX = targetObj->obj_loc_x1(); int targetLocY = targetObj->obj_loc_y1(); /* int testLocX, testLocY; int index, unitIndex; int maxWidth=0, maxHeight=0; Unit* unitPtr; int w, h; int rangeAttack=0, closeAttack=0; int minAttackRange = 0; int distance; Unit** arrayForRangeAttack=NULL, **arrayForCloseAttack=NULL; int numberAttacking = 0; */ //--looking for the maximum range, size of the units ---// //--and counting how many units will do range attack and close attack respectively---// /* for(int i=1; i<=size(); i++) { unitPtr = get_unit(i); if(!unitPtr->can_attack()) continue; //---------------------------------------------// if(unitPtr->cur_action == SPRITE_ATTACK && unitPtr->cur_order.para == targetObjRecno) { numberAttacking++; continue; } // ##### begin Gilbert 4/11 ######// // distance = unitPtr->cal_distance(targetLocX, targetLocY, targetWidth, targetHeight); distance = unitPtr->area_distance(targetObj); // ##### end Gilbert 4/11 ######// unitPtr->choose_best_attack_mode(distance, targetObj->obj_mobile_type()); if(unitPtr->obj_loc_width() > maxWidth) maxWidth = unitPtr->obj_loc_width(); if(unitPtr->obj_loc_height() > maxHeight) maxHeight = unitPtr->obj_loc_height(); if((unitPtr->attack_range() < minAttackRange) && (unitPtr->attack_range()>1)) minAttackRange = unitPtr->attack_range(); if(unitPtr->attack_range() > 1) rangeAttack++; else closeAttack++; } //---------------------------------------------------------// // err_when(!rangeAttack && !closeAttack); if(!rangeAttack && !closeAttack) return; if(rangeAttack) arrayForRangeAttack = (Unit**) mem_add(sizeof(Unit*)*rangeAttack); if(closeAttack) arrayForCloseAttack = (Unit**) mem_add(sizeof(Unit*)*closeAttack); int iRa = 0, iCa = 0; //---- separate the units into two arrays by means of their attacking mode ---// for(i=1; i<=size(); i++) { unitPtr = get_unit(i); if(!unitPtr->can_attack()) continue; if(unitPtr->cur_action == SPRITE_ATTACK && unitPtr->cur_order.para == targetObjRecno) continue; if(unitPtr->attack_range()>1) arrayForRangeAttack[iRa++] = unitPtr; else arrayForCloseAttack[iCa++] = unitPtr; } err_when(!maxWidth); err_when(!maxHeight); //----- assign a good location for the units to undergo range attack -----// if(rangeAttack) { int xLoc1 = max(targetLocX-minAttackRange, 0); int yLoc1 = max(targetLocY-minAttackRange, 0); int xLoc2 = min(targetLocX+targetWidth-1+minAttackRange, MAX_WORLD_X_LOC-1); int yLoc2 = min(targetLocY+targetHeight-1+minAttackRange, MAX_WORLD_Y_LOC-1); int checkXLoc, checkYLoc; unitIndex = 0; unitPtr = arrayForRangeAttack[unitIndex]; //-------- checking for surrounding location ----------// for(checkXLoc=xLoc1; checkXLoc<=xLoc2; checkXLoc++) { if(unitPtr->can_move(checkXLoc, yLoc1)) { unitPtr->attack_loc_offset_x = checkXLoc-targetLocX; unitPtr->attack_loc_offset_y = yLoc1-targetLocY; if(unitPtr->obj_loc_width()>1) checkXLoc += (unitPtr->obj_loc_width()-1); if(unitIndex<rangeAttack-1) unitPtr = arrayForRangeAttack[++unitIndex]; else break; } } if(unitIndex < rangeAttack) { for(checkYLoc=yLoc1+1; checkYLoc<yLoc2; checkYLoc++) { if(unitPtr->can_move(xLoc1, checkYLoc)) { unitPtr->attack_loc_offset_x = xLoc1-targetLocX; unitPtr->attack_loc_offset_y = checkYLoc-targetLocY; if(unitPtr->obj_loc_height() > 1) checkYLoc += (unitPtr->obj_loc_height()-1); if(unitIndex < rangeAttack-1) unitPtr = arrayForRangeAttack[++unitIndex]; else break; } } } if(unitIndex < rangeAttack) { for(checkXLoc=xLoc1; checkXLoc<=xLoc2; checkXLoc++) { if(unitPtr->can_move(checkXLoc, yLoc2)) { unitPtr->attack_loc_offset_x = checkXLoc-targetLocX; unitPtr->attack_loc_offset_y = yLoc2-targetLocY; if(unitPtr->obj_loc_width() > 1) checkXLoc+= (unitPtr->obj_loc_width()-1); if(unitIndex < rangeAttack-1) unitPtr= arrayForRangeAttack[++unitIndex]; else break; } } } if(unitIndex < rangeAttack) { for(checkYLoc=yLoc1+1; checkYLoc<yLoc2; checkYLoc++) { if(unitPtr->can_move(xLoc2, checkYLoc)) { unitPtr->attack_loc_offset_x = xLoc2-targetLocX; unitPtr->attack_loc_offset_y = checkYLoc-targetLocY; if(unitPtr->obj_loc_height() > 1) checkYLoc+=(unitPtr->obj_loc_height()-1); if(unitIndex < rangeAttack-1) unitPtr = arrayForRangeAttack[++unitIndex]; else break; } } } if(unitIndex < rangeAttack) { for(; unitIndex<rangeAttack; unitIndex++) { unitPtr = arrayForRangeAttack[unitIndex]; //--settting attack_loc_offset_? to 0 will make them cannot attack --// unitPtr->attack_loc_offset_x = 0; unitPtr->attack_loc_offset_y = 0; } } } //---- finding a good location for the units undergoing close attack -----// if(closeAttack) { unitIndex = 0; unitPtr = arrayForCloseAttack[unitIndex]; if((testLocY=targetLocY-maxHeight) >= 0) //has top edge { w = unitPtr->obj_loc_width(); while(w>=0) { if(targetLocX >= w) { index = -w; break; } w--; } err_when(index>0); for(; index<targetWidth; index++) { if(unitPtr->can_move(targetLocX+index, testLocY)) { unitPtr->attack_loc_offset_x = index; unitPtr->attack_loc_offset_y = -maxHeight; if(unitPtr->obj_loc_width() > 1) index += (unitPtr->obj_loc_width()-1); if(unitIndex < closeAttack-1) unitPtr = arrayForCloseAttack[++unitIndex]; //get_next_unit else break; } } } if((unitIndex < closeAttack) && ((testLocX = targetLocX + targetWidth) <= MAX_WORLD_X_LOC-maxWidth)) //has right edge { h = unitPtr->obj_loc_height(); while(h>=0) { if(targetLocY >= h) { index = -h; break; } h--; } err_when(index>0); for(; index<targetHeight; index++) { if(unitPtr->can_move(testLocX, targetLocY+index)) { unitPtr->attack_loc_offset_x = targetWidth; unitPtr->attack_loc_offset_y = index; if(unitPtr->obj_loc_height() > 1) index += (unitPtr->obj_loc_height()-1); if(unitIndex < closeAttack-1) unitPtr = arrayForCloseAttack[++unitIndex]; //get next unit else break; } } } if((unitIndex < closeAttack) && ((testLocY = targetLocY + targetHeight) <= MAX_WORLD_Y_LOC-maxHeight)) //has bottom edge { w = unitPtr->obj_loc_width(); while(w>=0) { if(targetLocX+targetWidth<=MAX_WORLD_X_LOC-w) { index = targetWidth-(unitPtr->obj_loc_width()-w); break; } w--; } for(; index>=0; index--) { if(unitPtr->can_move(targetLocX+index, testLocY)) { unitPtr->attack_loc_offset_x = index; unitPtr->attack_loc_offset_y = targetHeight; if(unitIndex < closeAttack-1) { unitPtr = arrayForCloseAttack[++unitIndex]; if(unitPtr->obj_loc_width() > 1) index -= (unitPtr->obj_loc_width()-1); } else break; } } } if(unitIndex < closeAttack && ((testLocX = targetLocX-maxWidth) >=0 )) //has left edge { h = unitPtr->obj_loc_height(); while(h>=0) { if(targetLocY+targetHeight<=MAX_WORLD_Y_LOC-h) { index = targetHeight-(unitPtr->obj_loc_height()-h); break; } h--; } for(; index>=0; index--) { if(unitPtr->can_move(testLocX, targetLocY+index)) { unitPtr->attack_loc_offset_x = -1; unitPtr->attack_loc_offset_y = index; if(unitIndex < closeAttack-1) { unitPtr = arrayForCloseAttack[++unitIndex]; if(unitPtr->obj_loc_height() > 1) index -= (unitPtr->obj_loc_height()-1); } else break; } } } //----for those who cannot find a good position, cannot attack //---- setting the attack_loc_offset_? to 0 means they cannot attack -----// if(unitIndex < closeAttack) { while(unitIndex < closeAttack-1) { unitPtr->attack_loc_offset_x = 0; unitPtr->attack_loc_offset_y = 0; unitPtr = arrayForCloseAttack[++unitIndex]; } unitPtr->attack_loc_offset_x = 0; unitPtr->attack_loc_offset_y = 0; } } */ cluster_units_for_attack(targetObjRecno, targetLocX, targetLocY, targetWidth, targetHeight); /* if(arrayForRangeAttack) mem_del(arrayForRangeAttack); if(arrayForCloseAttack) mem_del(arrayForCloseAttack); */ }
// ----- begin of function ScenarioEditor::disp_monster_view ------// // void ScenarioEditor::disp_monster_view() { if( power.command_id ) return; int drawMarker = 0; int validAction = 0; int markerX1, markerY1, markerX2, markerY2; int xLoc, yLoc; char mobileType; if( mouse.in_area(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2) ) { // destruction marker if there is a human Location *locPtr = power.test_detect(mouse.cur_x, mouse.cur_y, &mobileType, &xLoc, &yLoc); if( locPtr && locPtr->base_obj_recno() ) { BaseObj *baseObj = base_obj_array[locPtr->base_obj_recno()]; drawMarker = 1; validAction = 1; markerX1 = baseObj->obj_loc_x1(); markerY1 = baseObj->obj_loc_y1(); markerX2 = baseObj->obj_loc_x2(); markerY2 = baseObj->obj_loc_y2(); } // construction marker else if( world.zoom_matrix->get_detect_location(mouse.cur_x, mouse.cur_y, &xLoc, &yLoc, NULL) ) { locPtr = world.get_loc( xLoc, yLoc ); 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) ) { validAction = 1; } markerX1 = xLoc; markerY1 = yLoc; markerX2 = xLoc + spriteInfo->loc_width -1; markerY2 = yLoc + spriteInfo->loc_height -1; drawMarker = markerX2 < MAX_WORLD_X_LOC && markerY2 < MAX_WORLD_Y_LOC; } 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) ) { validAction = 1; } markerX1 = xLoc; markerY1 = yLoc; markerX2 = xLoc + firm_res[firmGroup->firm_id]->loc_width - 1; markerY2 = yLoc + firm_res[firmGroup->firm_id]->loc_height - 1; drawMarker = markerX2 < MAX_WORLD_X_LOC && markerY2 < MAX_WORLD_Y_LOC; } } } // ------ draw marker -------// if( drawMarker ) { draw_marker( validAction, markerX1, markerY1, markerX2, markerY2 ); } }
//----- Begin of function Nation::consider_military_aid -----// // int Nation::consider_military_aid(TalkMsg* talkMsg) { Nation* fromNation = nation_array[talkMsg->from_nation_recno]; NationRelation* fromRelation = get_relation(talkMsg->from_nation_recno); //----- don't aid too frequently ------// if( info.game_date < fromRelation->last_military_aid_date + 200 - pref_allying_tendency ) return 0; //------- only when the AI relation >= 60 --------// if( fromRelation->ai_relation_level < 60 ) return 0; //--- if the requesting nation is not at war now ----// if( !fromNation->is_at_war() ) return 0; //---- can't aid if we are at war ourselves -----// if( is_at_war() ) return 0; //--- if the nation is having a financial difficulty, it won't agree ---// if( cash < 2000 * pref_cash_reserve / 100 ) return 0; //----- can't aid if we are too weak ourselves ---// if( ai_general_count*10 + total_human_count + total_monster_count < 100-pref_military_courage/2 ) { return 0; } //----- see what units are attacking the nation -----// if( unit_array.is_deleted(fromNation->last_attacker_obj_recno) ) return 0; BaseObj* baseObj = base_obj_array[ fromNation->last_attacker_obj_recno ]; if( baseObj->nation_recno == nation_recno ) // if it's our own units return 0; if( baseObj->nation_recno == 0 ) return 0; if( !baseObj->is_visible() ) return 0; //------ only attack if it's a common enemy to us and our ally -----// if( get_relation(baseObj->nation_recno)->status != RELATION_HOSTILE ) return 0; //------- calculate the combat level of the target units there ------// int hasWar; int targetCombatLevel = mobile_defense_combat_level( baseObj->obj_loc_x1(), baseObj->obj_loc_y1(), baseObj->nation_recno, 0, hasWar ); if( ai_attack_target(baseObj->obj_loc_x1(), baseObj->obj_loc_y1(), targetCombatLevel, 0, 1 ) ) //0-not defense mode, 1-just move to flag { fromRelation->last_military_aid_date = info.game_date; return 1; } return 0; }