/* * 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 : OUNITAAC.CPP //Description : Object UnitArray - misc functions #include #include #include #include #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 //--------- Begin of function UnitArray::divide_array ---------// // divide units into arrays by their mobile_type // // excludeSelectedLocUnit - (default 0) // void UnitArray::divide_array(int locX, int locY, short* selectedArray, int selectedCount, int excludeSelectedLocUnit) { err_when( selectedCount < 0 ); selected_land_unit_count = 0; selected_sea_unit_count = 0; selected_air_unit_count = 0; selected_land_unit_array = NULL; selected_sea_unit_array = NULL; selected_air_unit_array = NULL; int unitRecno; if(excludeSelectedLocUnit) { Location *locPtr = world.get_loc(locX, locY); short targetMobileType = locPtr->has_any_unit(); unitRecno = targetMobileType ? locPtr->unit_recno(targetMobileType) : 0; } selected_land_unit_array = (short*) mem_add(sizeof(short)*selectedCount); selected_sea_unit_array = (short*) mem_add(sizeof(short)*selectedCount); selected_air_unit_array = (short*) mem_add(sizeof(short)*selectedCount); memset(selected_land_unit_array, 0, sizeof(short)*selectedCount); memset(selected_sea_unit_array, 0, sizeof(short)*selectedCount); memset(selected_air_unit_array, 0, sizeof(short)*selectedCount); Unit *unitPtr; int curRecno; for(int i=0; imobile_type) { case UNIT_LAND: selected_land_unit_array[selected_land_unit_count++] = curRecno; break; case UNIT_SEA: selected_sea_unit_array[selected_sea_unit_count++] = curRecno; break; case UNIT_AIR: selected_air_unit_array[selected_air_unit_count++] = curRecno; break; default: err_here(); break; } } } //----------- End of function UnitArray::divide_array -----------// //--------- Begin of function UnitArray::set_group_id ---------// // Set group id for the selected units // void UnitArray::set_group_id(short* selectedArray, int selectedCount) { //-------------------------------------------------// // set unit cur_action and unit_group_id //-------------------------------------------------// DWORD curGroupId = unit_array.cur_group_id++; for(int j=0; jis_visible()); err_when(unitPtr->hit_points<=0); unitPtr->unit_group_id = curGroupId; err_if(unitPtr->cur_action==SPRITE_IDLE && (unitPtr->cur_x!=unitPtr->next_x || unitPtr->cur_y!=unitPtr->next_y)) err_here(); if( unitPtr->cur_action == SPRITE_IDLE ) //**maybe need to include SPRITE_ATTACK as well unitPtr->set_ready(); } } //----------- End of function UnitArray::set_group_id -----------// //--------- Begin of function UnitArray::stop ---------// // // selectedUnitArray - an array of recno of selected units. // (the array should be terminated with 0) // selectedCount - no. of selected units. // [char] remoteAction - whether this is an action carried out by a remote machine or not. // (default: 0) // void UnitArray::stop(short* selectedUnitArray, int selectedCount, char remoteAction) { //-------- if it's a multiplayer game --------// // // Queue the action. // // Local: this action will be processed when all action messages of all // remote players are ready from the next frame. // // Remote: this action will be processed when the remote has received // frame sync notification from all other players. // //--------------------------------------------// if( !remoteAction && remote.is_enable() ) { short* shortPtr = (short*) remote.new_send_queue_msg(MSG_UNIT_STOP, sizeof(short) * (1+selectedCount) ); shortPtr[0] = selectedCount; memcpy( shortPtr+1, selectedUnitArray, sizeof(short) * selectedCount ); } else { DWORD curGroupId = unit_array.cur_group_id++; //-------------- stop now ---------------// err_when( selectedCount > 10000 ); // error Unit* unitPtr; for( int i=0 ; iunit_group_id = curGroupId; unitPtr->stop2(); } } } //----------- End of function UnitArray::stop -----------// //--------- Begin of function UnitArray::stop_all_war ---------// // Stop all the units that is in war with the specified nation // and stop all the units of the specified nation that is in war // with other nations // // oldNationReno - the nation_renco of the specified nation // void UnitArray::stop_all_war(short oldNationRecno) { Unit *unitPtr, *targetUnit; Firm *targetFirm; Town *targetTown; Location *targetLoc; char targetType; short targetRecno; int targetXLoc, targetYLoc; for(int i=size(); i>0; --i) { if(is_deleted(i)) continue; unitPtr = operator[](i); if(!unitPtr->is_visible()) continue; if(unitPtr->nation_recno==oldNationRecno) { //------ stop all attacking unit with nation_recno = oldNationRecno -----// if(unitPtr->is_action_attack()) unitPtr->stop2(KEEP_DEFENSE_MODE); } else if(unitPtr->is_action_attack()) { //---- stop all attacking unit with target's nation_recno = oldNationRecno ----// if(unitPtr->action_mode2==ACTION_AUTO_DEFENSE_ATTACK_TARGET) { targetType = unitPtr->action_mode; targetRecno = unitPtr->action_para; targetXLoc = unitPtr->action_x_loc; targetYLoc = unitPtr->action_y_loc; } else { targetType = unitPtr->action_mode2; targetRecno = unitPtr->action_para2; targetXLoc = unitPtr->action_x_loc2; targetYLoc = unitPtr->action_y_loc2; } switch(targetType) { case ACTION_ATTACK_UNIT: case ACTION_DEFEND_TOWN_ATTACK_TARGET: case ACTION_MONSTER_DEFEND_ATTACK_TARGET: if(is_deleted(targetRecno)) continue; targetUnit = operator[](targetRecno); if(targetUnit->nation_recno==oldNationRecno) unitPtr->stop2(KEEP_DEFENSE_MODE); break; case ACTION_ATTACK_FIRM: if(firm_array.is_deleted(targetRecno)) continue; targetFirm = firm_array[targetRecno]; if(targetFirm->nation_recno==oldNationRecno) unitPtr->stop2(KEEP_DEFENSE_MODE); break; case ACTION_ATTACK_TOWN: if(town_array.is_deleted(targetRecno)) continue; targetTown = town_array[targetRecno]; if(targetTown->nation_recno==oldNationRecno) unitPtr->stop2(KEEP_DEFENSE_MODE); break; case ACTION_ATTACK_WALL: targetLoc = world.get_loc(targetXLoc, targetYLoc); if(targetLoc->wall_nation_recno()==oldNationRecno) unitPtr->stop2(KEEP_DEFENSE_MODE); break; } } } } //----------- End of function UnitArray::stop_all_war -----------// //--------- Begin of function UnitArray::stop_war_between ---------// // stop the war between the two nations specified // // nationReno1 - the nation_renco of one of the nation // nationReno2 - the nation_renco of the other nation // void UnitArray::stop_war_between(short nationRecno1, short nationRecno2) { Unit *unitPtr, *targetUnit; Firm *targetFirm; Town *targetTown; Location *targetLoc; char targetType; short targetRecno; int targetXLoc, targetYLoc; for(int i=size(); i>0; --i) { if(is_deleted(i)) continue; unitPtr = operator[](i); if(!unitPtr->is_visible()) continue; if(unitPtr->nation_recno!=nationRecno1 && unitPtr->nation_recno!=nationRecno2) continue; if(unitPtr->is_action_attack()) { //---- stop all attacking unit with target's nation_recno = oldNationRecno ----// if(unitPtr->action_mode2==ACTION_AUTO_DEFENSE_ATTACK_TARGET) { targetType = unitPtr->action_mode; targetRecno = unitPtr->action_para; targetXLoc = unitPtr->action_x_loc; targetYLoc = unitPtr->action_y_loc; } else { targetType = unitPtr->action_mode2; targetRecno = unitPtr->action_para2; targetXLoc = unitPtr->action_x_loc2; targetYLoc = unitPtr->action_y_loc2; } switch(targetType) { case ACTION_ATTACK_UNIT: case ACTION_DEFEND_TOWN_ATTACK_TARGET: case ACTION_MONSTER_DEFEND_ATTACK_TARGET: if(is_deleted(targetRecno)) continue; targetUnit = operator[](targetRecno); if(targetUnit->nation_recno==nationRecno1 || targetUnit->nation_recno==nationRecno2) unitPtr->stop2(KEEP_DEFENSE_MODE); break; case ACTION_ATTACK_FIRM: if(firm_array.is_deleted(targetRecno)) continue; targetFirm = firm_array[targetRecno]; if(targetFirm->nation_recno==nationRecno1 || targetFirm->nation_recno==nationRecno2) unitPtr->stop2(KEEP_DEFENSE_MODE); break; case ACTION_ATTACK_TOWN: if(town_array.is_deleted(targetRecno)) continue; targetTown = town_array[targetRecno]; if(targetTown->nation_recno==nationRecno1 || targetTown->nation_recno==nationRecno2) unitPtr->stop2(KEEP_DEFENSE_MODE); break; case ACTION_ATTACK_WALL: targetLoc = world.get_loc(targetXLoc, targetYLoc); if(targetLoc->wall_nation_recno()==nationRecno1 || targetLoc->wall_nation_recno()==nationRecno2) unitPtr->stop2(KEEP_DEFENSE_MODE); break; } } } } //----------- End of function UnitArray::stop_war_between -----------// //--------- Begin of function UnitArray::stop_attack_unit ---------// // stop all units that is attacking the specified unit // // unitRecno - unit_recno of the specified unit // void UnitArray::stop_attack_unit(short unitRecno) { if(nation_hand_over_flag) return; Unit *unitPtr; for(int i=size(); i>0; --i) { if(is_deleted(i)) continue; unitPtr = operator[](i); if(!unitPtr->is_visible()) continue; if((unitPtr->action_para==unitRecno && unitPtr->action_mode==ACTION_ATTACK_UNIT) || (unitPtr->action_para2==unitRecno && unitPtr->action_mode2==ACTION_ATTACK_UNIT)) unitPtr->stop2(KEEP_DEFENSE_MODE); } } //----------- End of function UnitArray::stop_attack_unit -----------// //--------- Begin of function UnitArray::stop_attack_firm ---------// // stop all units that is attacking the specified firm // // firmRecno - the firm_recno of the firm // void UnitArray::stop_attack_firm(short firmRecno) { if(nation_hand_over_flag) return; Unit *unitPtr; for(int i=size(); i>0; --i) { if(is_deleted(i)) continue; unitPtr = operator[](i); if(!unitPtr->is_visible()) continue; if((unitPtr->action_para==firmRecno && unitPtr->action_mode==ACTION_ATTACK_FIRM) || (unitPtr->action_para2==firmRecno && unitPtr->action_mode2==ACTION_ATTACK_FIRM)) unitPtr->stop2(KEEP_DEFENSE_MODE); } } //----------- End of function UnitArray::stop_attack_firm -----------// //--------- Begin of function UnitArray::stop_attack_town ---------// // stop all units that is attacking the specified town // // townRecno - the town_recno of the specified town // void UnitArray::stop_attack_town(short townRecno) { if(nation_hand_over_flag) return; Unit *unitPtr; for(int i=size(); i>0; --i) { if(is_deleted(i)) continue; unitPtr = operator[](i); if(!unitPtr->is_visible()) continue; if((unitPtr->action_para==townRecno && unitPtr->action_mode==ACTION_ATTACK_TOWN) || (unitPtr->action_para2==townRecno && unitPtr->action_mode2==ACTION_ATTACK_TOWN)) unitPtr->stop2(KEEP_DEFENSE_MODE); } } //----------- End of function UnitArray::stop_attack_town -----------// //--------- Begin of function UnitArray::assign ---------// // group assign to firm/town/unit // // destX - x location assigned to // destY - y location assigned to // divided - whether the array is divied by divide_array(...) (1 - divided, 0 not) // remoteAction - // [short*] selectedArray - unit_recno of the selected units (default: NULL) // [int] selectedCount - number of selected units (default: 0) // void UnitArray::assign(int destX, int destY, int divided, char remoteAction, short* selectedArray, int selectedCount) { err_when(destX<0 || destY<0 || destX>MAX_WORLD_X_LOC-1 || destY>MAX_WORLD_Y_LOC-1); //###### begin trevor 25/8 #######// //--- set the destination to the top left position of the town/firm ---// Location* locPtr = world.get_loc(destX, destY); //---- if there is a firm on this location -----// if( locPtr->is_firm() ) { Firm* firmPtr = firm_array[locPtr->firm_recno()]; destX = firmPtr->loc_x1; destY = firmPtr->loc_y1; } //---- if there is a town on this location -----// else if( locPtr->is_town() ) { Town* townPtr = town_array[locPtr->town_recno()]; destX = townPtr->loc_x1; destY = townPtr->loc_y1; } //###### end trevor 25/8 #######// //-------------------------------------------// Unit* unitPtr; int freeMemory = 0; if( selectedArray == NULL) { selectedArray = (short*) mem_add(sizeof(short)*size()); selectedCount = 0; freeMemory = 1; // find myself for(int i=size(); i>0; i--) { if(is_deleted(i)) continue; unitPtr = operator[](i); //err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0); if(!unitPtr->is_visible()) continue; if( unitPtr->selected_flag && unitPtr->is_own() ) { err_when(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE); selectedArray[selectedCount++] = i; } } } if(!remoteAction && remote.is_enable()) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_ASSIGN, sizeof(short) * (4+selectedCount)); shortPtr[0] = destX; shortPtr[1] = destY; shortPtr[2] = selectedCount; shortPtr[3] = divided; memcpy(shortPtr+4, selectedArray, sizeof(short)*selectedCount); } else { if(!divided) { for(int j=0; j< selectedCount; ++j) { int i = selectedArray[j]; if(is_deleted(i)) continue; unitPtr = operator[](i); //unit_array[i]; //### begin trevor 7/7#######// err_when(!unitPtr->is_visible() ); err_when( unitPtr->hit_points<=0 ); //### end trevor 7/7#######// unitPtr->stop2(); } //--------- divide the unit by their mobile_type ------------// divide_array(destX, destY, selectedArray, selectedCount); if(selected_land_unit_count) assign(destX, destY, 1, remoteAction, selected_land_unit_array, selected_land_unit_count); if(selected_sea_unit_count) { Location *locPtr = world.get_loc(destX, destY); if(locPtr->is_firm()) { err_when(firm_array.is_deleted(locPtr->firm_recno())); Firm *firmPtr = firm_array[locPtr->firm_recno()]; if(firmPtr->firm_id==FIRM_HARBOR) // recursive call assign(destX, destY, 1, remoteAction, selected_sea_unit_array, selected_sea_unit_count); else ship_to_beach(destX, destY, 1, selected_sea_unit_array, selected_sea_unit_count, remoteAction); } //else if(locPtr->is_town()) else { err_when(town_array.is_deleted(locPtr->town_recno())); ship_to_beach(destX, destY, 1, selected_sea_unit_array, selected_sea_unit_count, remoteAction); } } if(selected_air_unit_count) // no assign for air units move_to(destX, destY, 1, selected_air_unit_array, selected_air_unit_count, remoteAction); //------------ deinit static variables ------------// selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0; mem_del(selected_land_unit_array); mem_del(selected_sea_unit_array); mem_del(selected_air_unit_array); } else { //---------- set unit to assign -----------// if(selectedCount<2) { unitPtr = (Unit*) get_ptr(selectedArray[0]); err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0); if(unitPtr->sprite_info->loc_width<=1) { unitPtr->unit_group_id = unit_array.cur_group_id++; unitPtr->assign(destX, destY); } else // move to object surrounding { Location *locPtr = world.get_loc(destX, destY); if(locPtr->is_firm()) unitPtr->move_to_firm_surround(destX, destY, unitPtr->sprite_info->loc_width, unitPtr->sprite_info->loc_height, locPtr->firm_recno()); else if(locPtr->is_town()) unitPtr->move_to_town_surround(destX, destY, unitPtr->sprite_info->loc_width, unitPtr->sprite_info->loc_height); else if(locPtr->has_unit(UNIT_LAND)) unitPtr->move_to_unit_surround(destX, destY, unitPtr->sprite_info->loc_width, unitPtr->sprite_info->loc_height, locPtr->unit_recno(UNIT_LAND)); } } else // for more than one unit selecting, call group_assign() to take care of it { set_group_id(selectedArray, selectedCount); group_assign(destX, destY, selectedArray, selectedCount); } } } if( freeMemory ) mem_del(selectedArray); } //----------- End of function UnitArray::assign -----------// //--------- Begin of function UnitArray::group_assign ---------// // destX - x location assigned to // destY - y location assigned to // selectedArray - unit recno of the selected units // selectedCount - num of selected units // void UnitArray::group_assign(int destX, int destY, short* selectedArray, int selectedCount) { enum { ASSIGN_TYPE_UNIT = 1, ASSIGN_TYPE_FIRM, ASSIGN_TYPE_TOWN, }; Location *locPtr = world.get_loc(destX, destY); int assignType = 0; // 1 for unit, 2 for firm, 3 for town int miscNo = 0; // usedd to store the recno of the object if(locPtr->has_unit(UNIT_LAND)) { assignType = ASSIGN_TYPE_UNIT; miscNo = locPtr->unit_recno(UNIT_LAND); } else if(locPtr->is_firm()) { assignType = ASSIGN_TYPE_FIRM; miscNo = firm_array[locPtr->firm_recno()]->firm_id; } else if(locPtr->is_town()) { assignType = ASSIGN_TYPE_TOWN; miscNo = 0; } else err_here(); Unit* unitPtr; for(int i=0; iis_visible() || unitPtr->hit_points<=0); if(unitPtr->sprite_info->loc_width<=1) unitPtr->assign(destX, destY, i+1); // the thrid parameter is used to generate different result for the searching else { //-----------------------------------------------------------------// // for 2x2 unit, unable to assign, so move to the surrounding //-----------------------------------------------------------------// switch(assignType) { case ASSIGN_TYPE_UNIT: unitPtr->move_to_unit_surround(destX, destY, unitPtr->sprite_info->loc_width, unitPtr->sprite_info->loc_height, miscNo); break; // is a unit case ASSIGN_TYPE_FIRM: unitPtr->move_to_firm_surround(destX, destY, unitPtr->sprite_info->loc_width, unitPtr->sprite_info->loc_height, miscNo); break; // is a firm case ASSIGN_TYPE_TOWN: unitPtr->move_to_town_surround(destX, destY, unitPtr->sprite_info->loc_width, unitPtr->sprite_info->loc_height); break; // is a town default: err_here(); break; } } } } //----------- End of function UnitArray::group_assign -----------// //--------- Begin of function UnitArray::assign_to_camp ---------// // destX - x location where the camp is // destY - y location where the camp is // remoteAction - // [short*] selectedUnitArray - recno of the selected units (default: NULL) // [int] selectedCount - number of selected units (default: 0) // void UnitArray::assign_to_camp(int destX, int destY, char remoteAction, short* selectedUnitArray, int selectedCount) { divide_array(destX, destY, selectedUnitArray, selectedCount); if(selected_land_unit_count) { int assignCount=0, moveCount=0; short *assignArray = (short*) mem_add(sizeof(short)*selected_land_unit_count); short *moveArray = (short*) mem_add(sizeof(short)*selected_land_unit_count); char unitClass; Unit *unitPtr; memset(assignArray, 0, sizeof(short)*selected_land_unit_count); memset(moveArray, 0, sizeof(short)*selected_land_unit_count); //----------------------------------------------------------------// // Only human and weapon can be assigned to the camp. Others are // ordered to move to camp as close as possible. //----------------------------------------------------------------// for(int i=0; iunit_id]->unit_class; if(unitClass==UNIT_CLASS_HUMAN || unitClass==UNIT_CLASS_WEAPON) assignArray[assignCount++] = selectedUnitArray[i]; else moveArray[moveCount++] = selectedUnitArray[i]; } if(assignCount) assign(destX, destY, 1, remoteAction, assignArray, assignCount); if(moveCount) move_to(destX, destY, 1, moveArray, moveCount, remoteAction); mem_del(assignArray); mem_del(moveArray); } if(selected_sea_unit_count) ship_to_beach(destX, destY, 1, selected_sea_unit_array, selected_sea_unit_count, remoteAction); if(selected_air_unit_count) move_to(destX, destY, 1, selected_air_unit_array, selected_air_unit_count, remoteAction); //---------------- deinit static parameters ---------------// selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0; mem_del(selected_land_unit_array); mem_del(selected_sea_unit_array); mem_del(selected_air_unit_array); } //----------- End of function UnitArray::assign_to_camp -----------// //--------- Begin of function UnitArray::settle ---------// // destX - x location settle to // destY - y location settle to // divided - whether the selected is divided into subgroup, (1 = divided, 0 = not) // remoteAction - // [short*] selectedArray - the recno of the selected units (default: NULL) // [int] selectedCount - num of selected units (default: 0) // void UnitArray::settle(int destX, int destY, int divided, char remoteAction, short* selectedArray, int selectedCount) { Unit* unitPtr; int freeMemory = 0; if(selectedArray == NULL) { selectedArray = (short*) mem_add(sizeof(short)*size()); selectedCount = 0; freeMemory = 1; // find myself for(int i=size(); i>0; i--) { if(is_deleted(i)) continue; unitPtr = operator[](i); //err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0); if(!unitPtr->is_visible()) continue; if( unitPtr->selected_flag && unitPtr->is_own() ) { err_when(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE); selectedArray[selectedCount++] = i; } } } if(!remoteAction && remote.is_enable()) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNITS_SETTLE, sizeof(short)*(4+selectedCount)); shortPtr[0] = destX; shortPtr[1] = destY; shortPtr[2] = selectedCount; shortPtr[3] = divided; memcpy(shortPtr+4, selectedArray, sizeof(short)*selectedCount); } else { if(!divided) { for(int j=0; j< selectedCount; ++j) { int i = selectedArray[j]; if(is_deleted(i)) continue; unitPtr = operator[](i); //unit_array[i]; err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0); unitPtr->stop2(); } divide_array(destX, destY, selectedArray, selectedCount); if(selected_land_unit_count) settle(destX, destY, 1, remoteAction, selected_land_unit_array, selected_land_unit_count); if(selected_sea_unit_count) ship_to_beach(destX, destY, 1, selected_sea_unit_array, selected_sea_unit_count, remoteAction); if(selected_air_unit_count) move_to(destX, destY, 1, selected_air_unit_array, selected_air_unit_count, remoteAction); //-------------- deinit static parameters --------------// selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0; mem_del(selected_land_unit_array); mem_del(selected_sea_unit_array); mem_del(selected_air_unit_array); } else { //---------- set unit to settle -----------// if(selectedCount<2) { unitPtr = (Unit*) get_ptr(selectedArray[0]); err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0); unitPtr->unit_group_id = unit_array.cur_group_id++; unitPtr->settle(destX, destY); } else { set_group_id(selectedArray, selectedCount); group_settle(destX, destY, selectedArray, selectedCount); } } } if(freeMemory) mem_del(selectedArray); } //----------- End of function UnitArray::settle -----------// //--------- Begin of function UnitArray::group_settle ---------// // destX - x location to settle to // destY - y location to settle to // selectedArray - recno. of selected units // selectedCount - num. of selected units // void UnitArray::group_settle(int destX, int destY, short* selectedArray, int selectedCount) { #ifdef DEBUG DWORD debugGroupId = (operator[](selectedArray[0]))->unit_group_id; #endif Unit* unitPtr; for(int i=0; iis_visible() || unitPtr->hit_points<=0); #ifdef DEBUG err_when(unitPtr->unit_group_id!=debugGroupId); #endif unitPtr->settle(destX, destY, i+1); } } //----------- End of function UnitArray::group_settle -----------// //--------- Begin of function UnitArray::assign_to_ship ---------// // shipXLoc - x location of the ship // shipYLoc - y location of the ship // divided - whether the selected groups is divided (1 - divided, 0 - not) // selectedArray - recno of selected units // selectedCount - num. of selected units // remoteAction - // void UnitArray::assign_to_ship(int shipXLoc, int shipYLoc, int divided, short* selectedArray, int selectedCount, char remoteAction, int shipRecno) { err_when(terrain_res[world.get_loc(shipXLoc, shipYLoc)->terrain_id]->average_type!=TERRAIN_OCEAN); err_when(!selectedCount || selectedCount>1000); if( !remoteAction && remote.is_enable() ) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNITS_ASSIGN_TO_SHIP, sizeof(short) * (5+selectedCount)); shortPtr[0] = shipXLoc; shortPtr[1] = shipYLoc; shortPtr[2] = shipRecno; shortPtr[3] = selectedCount; shortPtr[4] = divided; memcpy(shortPtr+5, selectedArray, sizeof(short)*selectedCount); return; } if(!divided) { divide_array(shipXLoc, shipYLoc, selectedArray, selectedCount); if(selected_sea_unit_count) // Note: the order to call ship unit first move_to(shipXLoc, shipYLoc, 1, selected_sea_unit_array, selected_sea_unit_count, remoteAction); if(selected_land_unit_count) assign_to_ship(shipXLoc, shipYLoc, 1, selected_land_unit_array, selected_land_unit_count, remoteAction, shipRecno); if(selected_air_unit_count) move_to(shipXLoc, shipYLoc, 1, selected_air_unit_array, selected_air_unit_count, remoteAction); //---------------- deinit static parameters -----------------// selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0; mem_del(selected_land_unit_array); mem_del(selected_sea_unit_array); mem_del(selected_air_unit_array); return; } else { // ###### begin Gilbert 5/8 ##########// // ----- dont not use shipXLoc, shipYLoc passed, use shipRecno --------// UnitMarine *shipPtr = (UnitMarine*) get_ptr(shipRecno); if( shipPtr && shipPtr->is_visible() ) { shipXLoc = shipPtr->next_x_loc(); shipYLoc = shipPtr->next_y_loc(); } else return; // ##### patch end Gilbert 5/8 #######// //------------------------------------------------------------------------------------// // find the closest unit to the ship //------------------------------------------------------------------------------------// int minDist=0x7FFFFF, dist, distX, distY; int closestUnitRecno = -1; Unit *unitPtr; int i; for(i=0; inext_x_loc()); distY = abs(shipYLoc - unitPtr->next_y_loc()); dist = (distX>distY) ? distX : distY; if(dist < minDist) { minDist = dist; closestUnitRecno = i; } } err_when(closestUnitRecno==-1); //------------------------------------------------------------------------------------// // If the seleceted units are distributed on different territories, select those unit // on the same territory as the closet unit for processing, there will be no action for // the rest units. //------------------------------------------------------------------------------------// DWORD curGroupId = unit_array.cur_group_id++; Unit *closestUnit = (Unit*) get_ptr(selectedArray[closestUnitRecno]); int closestUnitXLoc = closestUnit->next_x_loc(); int closestUnitYLoc = closestUnit->next_y_loc(); unsigned char defaultRegionId = world.get_loc(closestUnitXLoc, closestUnitYLoc)->region_id; short *newSelectedArray; int newSelectedCount = 0; if(selectedCount>1) { newSelectedArray = (short*) mem_add(sizeof(short)*selectedCount); memset(newSelectedArray, 0, sizeof(short)*selectedCount); for(i=0; inext_x_loc(), unitPtr->next_y_loc())->region_id == defaultRegionId) { newSelectedArray[newSelectedCount++] = selectedArray[i]; // on the same territory unitPtr->unit_group_id = curGroupId; } if(unitPtr->cur_action==SPRITE_IDLE) unitPtr->set_ready(); } err_when(newSelectedCount > selectedCount); } else { err_when(closestUnit->sprite_recno!=selectedArray[0]); newSelectedArray = (short*) mem_add(sizeof(short)); // only one unit newSelectedArray[0] = selectedArray[0]; newSelectedCount = 1; closestUnit->unit_group_id = curGroupId; } //-------------- ordering the ship move near the coast ----------------// int curXLoc = closestUnit->next_x_loc(); int curYLoc = closestUnit->next_y_loc(); // ##### patch begin Gilbert 5/8 #######// // UnitMarine *shipPtr = (UnitMarine*) get_ptr(world.get_unit_recno(shipXLoc, shipYLoc, UNIT_SEA)); // ##### patch end Gilbert 5/8 #######// int landX, landY; shipPtr->unit_group_id = curGroupId; shipPtr->ship_to_beach(curXLoc, curYLoc, landX, landY); if(landX!=-1 && landY!=-1) { //-------------- ordering the units ---------------// #define TRY_SIZE 5 int countLimit = TRY_SIZE*TRY_SIZE; //### begin alex 30/10 ###// int j, k, xShift, yShift, checkXLoc, checkYLoc; UCHAR regionId = world.get_loc(landX, landY)->region_id; Location *locPtr; for(i=0, k=0; icountLimit) k = 1; m.cal_move_around_a_point(k, TRY_SIZE, TRY_SIZE, xShift, yShift); checkXLoc = landX+xShift; checkYLoc = landY+yShift; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) continue; locPtr = world.get_loc(checkXLoc, checkYLoc); if(locPtr->region_id!=regionId || !locPtr->can_move(UNIT_LAND)) continue; unitPtr = (Unit*) get_ptr(newSelectedArray[i]); unitPtr->assign_to_ship(landX, landY, shipPtr->sprite_recno, k); break; } } //#### end alex 30/10 ####// } mem_del(newSelectedArray); } } //----------- End of function UnitArray::assign_to_ship -----------// //--------- Begin of function UnitArray::ship_to_beach ---------// // destX - x location the ship move to // destY - y location the ship move to // divided - whether the units are divided (1 - divided, 0 - not) // selectedArray - the recno. of the selected units // selectedCount - num. of selected units // remoteAction - // void UnitArray::ship_to_beach(int destX, int destY, int divided, short* selectedArray, int selectedCount, char remoteAction) { Unit *unitPtr; if( !remoteAction && remote.is_enable() ) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNITS_SHIP_TO_BEACH, sizeof(short) * (4+selectedCount)); shortPtr[0] = destX; shortPtr[1] = destY; shortPtr[2] = selectedCount; shortPtr[3] = divided; memcpy(shortPtr+4, selectedArray, sizeof(short)*selectedCount); return; } set_group_id(selectedArray, selectedCount); //--------------------------------------------------------------------// //--------------------------------------------------------------------// #define CHECK_SEA_DIMENSION 50 #define CHECK_SEA_SIZE CHECK_SEA_DIMENSION*CHECK_SEA_DIMENSION Location *locPtr = world.get_loc(destX, destY); UCHAR regionId = locPtr->region_id; int xShift, yShift, checkXLoc, checkYLoc; int landX, landY, seaX, seaY, tempX, tempY; int j=1, k, found; //--------------------------------------------------------------------// // find a unit that can carrying units. Let it to do the first searching. // Use the returned reference parameters (landX, landY) for the other // ships to calculate their final location to move to //--------------------------------------------------------------------// int i; for(i=0; iunit_id]->carry_unit_capacity>0) { unitPtr->ship_to_beach(destX, destY, landX, landY); // landX=landY=-1 if calling move_to() instead i++; break; } else unitPtr->move_to(destX, destY, 1); } int totalCheck = 0; for(; iunit_id]->carry_unit_capacity>0 && landX!=-1 && landY!=-1) { for(found=0; j<=CHECK_SEA_SIZE; j++, totalCheck++) { m.cal_move_around_a_point(j, CHECK_SEA_DIMENSION, CHECK_SEA_DIMENSION, xShift, yShift); if(j>=CHECK_SEA_SIZE) j = 1; if(totalCheck == CHECK_SEA_SIZE) { //--------------------------------------------------------------------// // can't handle this case //--------------------------------------------------------------------// unitPtr->ship_to_beach(landX, landY, tempX, tempY); totalCheck = 0; break; } seaX = landX+xShift; seaY = landY+yShift; if(seaX<0 || seaX>=MAX_WORLD_X_LOC || seaY<0 || seaY>=MAX_WORLD_Y_LOC) continue; locPtr = world.get_loc(seaX, seaY); if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN) continue; //--------------------------------------------------------------------// // if it is able to find a location around the surrounding location with // same region id we prefer, order the unit to move there. //--------------------------------------------------------------------// for(k=2; k<=9; k++) { m.cal_move_around_a_point(k, 3, 3, xShift, yShift); checkXLoc = seaX+xShift; checkYLoc = seaY+yShift; if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC) continue; locPtr = world.get_loc(checkXLoc, checkYLoc); if(locPtr->region_id!=regionId) continue; unitPtr->ship_to_beach(checkXLoc, checkYLoc, tempX, tempY); found++; err_when(unitPtr->result_node_array && unitPtr->result_node_count==unitPtr->result_node_recno && (unitPtr->result_node_array[unitPtr->result_node_count-1].node_x!=unitPtr->go_x>>ZOOM_X_SHIFT_COUNT || unitPtr->result_node_array[unitPtr->result_node_count-1].node_y!=unitPtr->go_y>>ZOOM_Y_SHIFT_COUNT)); break; } if(found) { totalCheck = 0; break; } } } else // cannot carry units unitPtr->move_to(destX, destY, 1); } } //----------- End of function UnitArray::ship_to_beach -----------// //----------- Begin of function UnitArray::divide_attack_by_nation -----------// // // units which can be controlled by nationRecno to attack are moved // to the front of the selectedArray, return is number of units passed // int UnitArray::divide_attack_by_nation(short nationRecno, short *selectedArray, int selectedCount) { // elements before i are pass, elements on or after passCount are not pass int loopCount = selectedCount+2; int passCount = selectedCount; for( int i = 0; i < passCount; ) { err_when(--loopCount == 0); short unitRecno = selectedArray[i]; // a clocked spy cannot be commanded by original nation to attack if( !is_deleted(unitRecno) && operator[](unitRecno)->nation_recno == nationRecno ) { // pass ++i; } else { // fail, swap [i] with [passCount-1] --passCount; selectedArray[i] = selectedArray[passCount]; selectedArray[passCount] = unitRecno; } } return passCount; } //----------- End of function UnitArray::divide_attack_by_nation -----------// //----------- Begin of function UnitArray::add_way_point -----------// // pointX - x location of the point to be added // pointY - y location of the point to be added // selectedArray - recno. of selected units // selectedCount - num. of selected units // remoteAction - // void UnitArray::add_way_point(int pointX, int pointY, short* selectedArray, int selectedCount, char remoteAction) { if(!remoteAction && remote.is_enable()) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_ADD_WAY_POINT, sizeof(short) * (3+selectedCount)); shortPtr[0] = pointX; shortPtr[1] = pointY; shortPtr[2] = selectedCount; memcpy(shortPtr+3, selectedArray, sizeof(short)*selectedCount); } else { DWORD groupId = unit_array.cur_group_id; Unit *unitPtr; int i; for(i=0; iunit_group_id = groupId; } unit_array.cur_group_id++; for(i=0; iadd_way_point(pointX, pointY); } } } //----------- End of function UnitArray::add_way_point -----------//