123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OUNITAAC.CPP
- //Description : Object UnitArray - misc functions
- #include <math.h>
- #include <ALL.h>
- #include <OVGA.h>
- #include <OSYS.h>
- #include <OSTR.h>
- #include <OREMOTE.h>
- #include <OWORLD.h>
- #include <ONATION.h>
- #include <OFIRM.h>
- #include <OTOWN.h>
- #include <OTERRAIN.h>
- #include <OU_MARI.h>
- #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
- //
- // <int> 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; i<selectedCount; i++)
- {
- curRecno = selectedArray[i];
- if(excludeSelectedLocUnit && curRecno==unitRecno)
- continue;
- unitPtr = (Unit*) get_ptr(curRecno);
- switch(unitPtr->mobile_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; j<selectedCount; j++)
- {
- Unit* unitPtr = (Unit*) get_ptr(selectedArray[j]);
- err_when(!unitPtr);
- err_when(!unitPtr->is_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 ---------//
- //
- // <short*> selectedUnitArray - an array of recno of selected units.
- // (the array should be terminated with 0)
- // <int> 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 ; i<selectedCount ; i++ )
- {
- unitPtr = (Unit*) get_ptr(selectedUnitArray[i]);
- unitPtr->unit_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
- //
- // <short> 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
- //
- // <short> nationReno1 - the nation_renco of one of the nation
- // <short> 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
- //
- // <short> 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
- //
- // <short> 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
- //
- // <short> 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
- //
- // <int> destX - x location assigned to
- // <int> destY - y location assigned to
- // <int> divided - whether the array is divied by divide_array(...) (1 - divided, 0 not)
- // <char> 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 : <xLoc> <yLoc> <no. of units> <unit recno ...>
- 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 ---------//
- // <int> destX - x location assigned to
- // <int> destY - y location assigned to
- // <short*> selectedArray - unit recno of the selected units
- // <int> 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; i<selectedCount; i++)
- {
- unitPtr = operator[](selectedArray[i]);
- err_when(!unitPtr->is_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 ---------//
- // <int> destX - x location where the camp is
- // <int> destY - y location where the camp is
- // <char> 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; i<selectedCount; i++)
- {
- err_when(unit_array.is_deleted(selectedUnitArray[i]));
- unitPtr = operator[](selectedUnitArray[i]);
- unitClass = unit_res[unitPtr->unit_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 ---------//
- // <int> destX - x location settle to
- // <int> destY - y location settle to
- // <int> divided - whether the selected is divided into subgroup, (1 = divided, 0 = not)
- // <char> 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 : <xLoc> <yLoc> <no. of units> <divided> <unit recno ...>
- 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 ---------//
- // <int> destX - x location to settle to
- // <int> destY - y location to settle to
- // <short*> selectedArray - recno. of selected units
- // <int> 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; i<selectedCount; i++)
- {
- unitPtr = operator[](selectedArray[i]);
- err_when(!unitPtr->is_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 ---------//
- // <int> shipXLoc - x location of the ship
- // <int> shipYLoc - y location of the ship
- // <int> divided - whether the selected groups is divided (1 - divided, 0 - not)
- // <short*> selectedArray - recno of selected units
- // <int> selectedCount - num. of selected units
- // <char> 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 : <xLoc> <yLoc> <ship recno> <no. of units> <divided> <unit recno ...>
- 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; i<selectedCount; i++)
- {
- unitPtr = (Unit*) get_ptr(selectedArray[i]);
- distX = abs(shipXLoc - unitPtr->next_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; i<selectedCount; i++)
- {
- unitPtr = (Unit*) get_ptr(selectedArray[i]);
- if(world.get_loc(unitPtr->next_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; i<newSelectedCount; i++)
- {
- for(j=1; j<countLimit; j++)
- {
- if(++k>countLimit)
- 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 ---------//
- // <int> destX - x location the ship move to
- // <int> destY - y location the ship move to
- // <int> divided - whether the units are divided (1 - divided, 0 - not)
- // <short*> selectedArray - the recno. of the selected units
- // <int> selectedCount - num. of selected units
- // <char> 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 : <xLoc> <yLoc> <no. of units> <divided> <unit recno ...>
- 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; i<selectedCount; i++) // for first unit
- {
- unitPtr = (Unit*) get_ptr(selectedArray[i]);
- if(unit_res[unitPtr->unit_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(; i<selectedCount; i++) // for the rest units
- {
- unitPtr = (Unit*) get_ptr(selectedArray[i]);
- if(unit_res[unitPtr->unit_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 -----------//
- // <int> pointX - x location of the point to be added
- // <int> pointY - y location of the point to be added
- // <short*> selectedArray - recno. of selected units
- // <int> selectedCount - num. of selected units
- // <char> remoteAction -
- //
- void UnitArray::add_way_point(int pointX, int pointY, short* selectedArray, int selectedCount, char remoteAction)
- {
- if(!remoteAction && remote.is_enable())
- {
- // packet structure : <xLoc> <yLoc> <no. of units> <unit recno ...>
- 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; i<selectedCount; ++i)
- {
- unitPtr = unit_array[selectedArray[i]];
- unitPtr->unit_group_id = groupId;
- }
- unit_array.cur_group_id++;
-
- for(i=0; i<selectedCount; ++i)
- {
- unitPtr = unit_array[selectedArray[i]];
- unitPtr->add_way_point(pointX, pointY);
- }
- }
- }
- //----------- End of function UnitArray::add_way_point -----------//
|