OUNITAAC.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OUNITAAC.CPP
  21. //Description : Object UnitArray - misc functions
  22. #include <math.h>
  23. #include <ALL.h>
  24. #include <OVGA.h>
  25. #include <OSYS.h>
  26. #include <OSTR.h>
  27. #include <OREMOTE.h>
  28. #include <OWORLD.h>
  29. #include <ONATION.h>
  30. #include <OFIRM.h>
  31. #include <OTOWN.h>
  32. #include <OTERRAIN.h>
  33. #include <OU_MARI.h>
  34. #ifdef NO_DEBUG_UNIT
  35. #undef err_when
  36. #undef err_here
  37. #undef err_if
  38. #undef err_else
  39. #undef err_now
  40. #define err_when(cond)
  41. #define err_here()
  42. #define err_if(cond)
  43. #define err_else
  44. #define err_now(msg)
  45. #undef DEBUG
  46. #endif
  47. //--------- Begin of function UnitArray::divide_array ---------//
  48. // divide units into arrays by their mobile_type
  49. //
  50. // <int> excludeSelectedLocUnit - (default 0)
  51. //
  52. void UnitArray::divide_array(int locX, int locY, short* selectedArray, int selectedCount, int excludeSelectedLocUnit)
  53. {
  54. err_when( selectedCount < 0 );
  55. selected_land_unit_count = 0;
  56. selected_sea_unit_count = 0;
  57. selected_air_unit_count = 0;
  58. selected_land_unit_array = NULL;
  59. selected_sea_unit_array = NULL;
  60. selected_air_unit_array = NULL;
  61. int unitRecno;
  62. if(excludeSelectedLocUnit)
  63. {
  64. Location *locPtr = world.get_loc(locX, locY);
  65. short targetMobileType = locPtr->has_any_unit();
  66. unitRecno = targetMobileType ? locPtr->unit_recno(targetMobileType) : 0;
  67. }
  68. selected_land_unit_array = (short*) mem_add(sizeof(short)*selectedCount);
  69. selected_sea_unit_array = (short*) mem_add(sizeof(short)*selectedCount);
  70. selected_air_unit_array = (short*) mem_add(sizeof(short)*selectedCount);
  71. memset(selected_land_unit_array, 0, sizeof(short)*selectedCount);
  72. memset(selected_sea_unit_array, 0, sizeof(short)*selectedCount);
  73. memset(selected_air_unit_array, 0, sizeof(short)*selectedCount);
  74. Unit *unitPtr;
  75. int curRecno;
  76. for(int i=0; i<selectedCount; i++)
  77. {
  78. curRecno = selectedArray[i];
  79. if(excludeSelectedLocUnit && curRecno==unitRecno)
  80. continue;
  81. unitPtr = (Unit*) get_ptr(curRecno);
  82. switch(unitPtr->mobile_type)
  83. {
  84. case UNIT_LAND:
  85. selected_land_unit_array[selected_land_unit_count++] = curRecno;
  86. break;
  87. case UNIT_SEA:
  88. selected_sea_unit_array[selected_sea_unit_count++] = curRecno;
  89. break;
  90. case UNIT_AIR:
  91. selected_air_unit_array[selected_air_unit_count++] = curRecno;
  92. break;
  93. default: err_here();
  94. break;
  95. }
  96. }
  97. }
  98. //----------- End of function UnitArray::divide_array -----------//
  99. //--------- Begin of function UnitArray::set_group_id ---------//
  100. // Set group id for the selected units
  101. //
  102. void UnitArray::set_group_id(short* selectedArray, int selectedCount)
  103. {
  104. //-------------------------------------------------//
  105. // set unit cur_action and unit_group_id
  106. //-------------------------------------------------//
  107. DWORD curGroupId = unit_array.cur_group_id++;
  108. for(int j=0; j<selectedCount; j++)
  109. {
  110. Unit* unitPtr = (Unit*) get_ptr(selectedArray[j]);
  111. err_when(!unitPtr);
  112. err_when(!unitPtr->is_visible());
  113. err_when(unitPtr->hit_points<=0);
  114. unitPtr->unit_group_id = curGroupId;
  115. err_if(unitPtr->cur_action==SPRITE_IDLE && (unitPtr->cur_x!=unitPtr->next_x || unitPtr->cur_y!=unitPtr->next_y))
  116. err_here();
  117. if( unitPtr->cur_action == SPRITE_IDLE ) //**maybe need to include SPRITE_ATTACK as well
  118. unitPtr->set_ready();
  119. }
  120. }
  121. //----------- End of function UnitArray::set_group_id -----------//
  122. //--------- Begin of function UnitArray::stop ---------//
  123. //
  124. // <short*> selectedUnitArray - an array of recno of selected units.
  125. // (the array should be terminated with 0)
  126. // <int> selectedCount - no. of selected units.
  127. // [char] remoteAction - whether this is an action carried out by a remote machine or not.
  128. // (default: 0)
  129. //
  130. void UnitArray::stop(short* selectedUnitArray, int selectedCount, char remoteAction)
  131. {
  132. //-------- if it's a multiplayer game --------//
  133. //
  134. // Queue the action.
  135. //
  136. // Local: this action will be processed when all action messages of all
  137. // remote players are ready from the next frame.
  138. //
  139. // Remote: this action will be processed when the remote has received
  140. // frame sync notification from all other players.
  141. //
  142. //--------------------------------------------//
  143. if( !remoteAction && remote.is_enable() )
  144. {
  145. short* shortPtr = (short*) remote.new_send_queue_msg(MSG_UNIT_STOP,
  146. sizeof(short) * (1+selectedCount) );
  147. shortPtr[0] = selectedCount;
  148. memcpy( shortPtr+1, selectedUnitArray, sizeof(short) * selectedCount );
  149. }
  150. else
  151. {
  152. DWORD curGroupId = unit_array.cur_group_id++;
  153. //-------------- stop now ---------------//
  154. err_when( selectedCount > 10000 ); // error
  155. Unit* unitPtr;
  156. for( int i=0 ; i<selectedCount ; i++ )
  157. {
  158. unitPtr = (Unit*) get_ptr(selectedUnitArray[i]);
  159. unitPtr->unit_group_id = curGroupId;
  160. unitPtr->stop2();
  161. }
  162. }
  163. }
  164. //----------- End of function UnitArray::stop -----------//
  165. //--------- Begin of function UnitArray::stop_all_war ---------//
  166. // Stop all the units that is in war with the specified nation
  167. // and stop all the units of the specified nation that is in war
  168. // with other nations
  169. //
  170. // <short> oldNationReno - the nation_renco of the specified nation
  171. //
  172. void UnitArray::stop_all_war(short oldNationRecno)
  173. {
  174. Unit *unitPtr, *targetUnit;
  175. Firm *targetFirm;
  176. Town *targetTown;
  177. Location *targetLoc;
  178. char targetType;
  179. short targetRecno;
  180. int targetXLoc, targetYLoc;
  181. for(int i=size(); i>0; --i)
  182. {
  183. if(is_deleted(i))
  184. continue;
  185. unitPtr = operator[](i);
  186. if(!unitPtr->is_visible())
  187. continue;
  188. if(unitPtr->nation_recno==oldNationRecno)
  189. {
  190. //------ stop all attacking unit with nation_recno = oldNationRecno -----//
  191. if(unitPtr->is_action_attack())
  192. unitPtr->stop2(KEEP_DEFENSE_MODE);
  193. }
  194. else if(unitPtr->is_action_attack())
  195. {
  196. //---- stop all attacking unit with target's nation_recno = oldNationRecno ----//
  197. if(unitPtr->action_mode2==ACTION_AUTO_DEFENSE_ATTACK_TARGET)
  198. {
  199. targetType = unitPtr->action_mode;
  200. targetRecno = unitPtr->action_para;
  201. targetXLoc = unitPtr->action_x_loc;
  202. targetYLoc = unitPtr->action_y_loc;
  203. }
  204. else
  205. {
  206. targetType = unitPtr->action_mode2;
  207. targetRecno = unitPtr->action_para2;
  208. targetXLoc = unitPtr->action_x_loc2;
  209. targetYLoc = unitPtr->action_y_loc2;
  210. }
  211. switch(targetType)
  212. {
  213. case ACTION_ATTACK_UNIT:
  214. case ACTION_DEFEND_TOWN_ATTACK_TARGET:
  215. case ACTION_MONSTER_DEFEND_ATTACK_TARGET:
  216. if(is_deleted(targetRecno))
  217. continue;
  218. targetUnit = operator[](targetRecno);
  219. if(targetUnit->nation_recno==oldNationRecno)
  220. unitPtr->stop2(KEEP_DEFENSE_MODE);
  221. break;
  222. case ACTION_ATTACK_FIRM:
  223. if(firm_array.is_deleted(targetRecno))
  224. continue;
  225. targetFirm = firm_array[targetRecno];
  226. if(targetFirm->nation_recno==oldNationRecno)
  227. unitPtr->stop2(KEEP_DEFENSE_MODE);
  228. break;
  229. case ACTION_ATTACK_TOWN:
  230. if(town_array.is_deleted(targetRecno))
  231. continue;
  232. targetTown = town_array[targetRecno];
  233. if(targetTown->nation_recno==oldNationRecno)
  234. unitPtr->stop2(KEEP_DEFENSE_MODE);
  235. break;
  236. case ACTION_ATTACK_WALL:
  237. targetLoc = world.get_loc(targetXLoc, targetYLoc);
  238. if(targetLoc->wall_nation_recno()==oldNationRecno)
  239. unitPtr->stop2(KEEP_DEFENSE_MODE);
  240. break;
  241. }
  242. }
  243. }
  244. }
  245. //----------- End of function UnitArray::stop_all_war -----------//
  246. //--------- Begin of function UnitArray::stop_war_between ---------//
  247. // stop the war between the two nations specified
  248. //
  249. // <short> nationReno1 - the nation_renco of one of the nation
  250. // <short> nationReno2 - the nation_renco of the other nation
  251. //
  252. void UnitArray::stop_war_between(short nationRecno1, short nationRecno2)
  253. {
  254. Unit *unitPtr, *targetUnit;
  255. Firm *targetFirm;
  256. Town *targetTown;
  257. Location *targetLoc;
  258. char targetType;
  259. short targetRecno;
  260. int targetXLoc, targetYLoc;
  261. for(int i=size(); i>0; --i)
  262. {
  263. if(is_deleted(i))
  264. continue;
  265. unitPtr = operator[](i);
  266. if(!unitPtr->is_visible())
  267. continue;
  268. if(unitPtr->nation_recno!=nationRecno1 && unitPtr->nation_recno!=nationRecno2)
  269. continue;
  270. if(unitPtr->is_action_attack())
  271. {
  272. //---- stop all attacking unit with target's nation_recno = oldNationRecno ----//
  273. if(unitPtr->action_mode2==ACTION_AUTO_DEFENSE_ATTACK_TARGET)
  274. {
  275. targetType = unitPtr->action_mode;
  276. targetRecno = unitPtr->action_para;
  277. targetXLoc = unitPtr->action_x_loc;
  278. targetYLoc = unitPtr->action_y_loc;
  279. }
  280. else
  281. {
  282. targetType = unitPtr->action_mode2;
  283. targetRecno = unitPtr->action_para2;
  284. targetXLoc = unitPtr->action_x_loc2;
  285. targetYLoc = unitPtr->action_y_loc2;
  286. }
  287. switch(targetType)
  288. {
  289. case ACTION_ATTACK_UNIT:
  290. case ACTION_DEFEND_TOWN_ATTACK_TARGET:
  291. case ACTION_MONSTER_DEFEND_ATTACK_TARGET:
  292. if(is_deleted(targetRecno))
  293. continue;
  294. targetUnit = operator[](targetRecno);
  295. if(targetUnit->nation_recno==nationRecno1 || targetUnit->nation_recno==nationRecno2)
  296. unitPtr->stop2(KEEP_DEFENSE_MODE);
  297. break;
  298. case ACTION_ATTACK_FIRM:
  299. if(firm_array.is_deleted(targetRecno))
  300. continue;
  301. targetFirm = firm_array[targetRecno];
  302. if(targetFirm->nation_recno==nationRecno1 || targetFirm->nation_recno==nationRecno2)
  303. unitPtr->stop2(KEEP_DEFENSE_MODE);
  304. break;
  305. case ACTION_ATTACK_TOWN:
  306. if(town_array.is_deleted(targetRecno))
  307. continue;
  308. targetTown = town_array[targetRecno];
  309. if(targetTown->nation_recno==nationRecno1 || targetTown->nation_recno==nationRecno2)
  310. unitPtr->stop2(KEEP_DEFENSE_MODE);
  311. break;
  312. case ACTION_ATTACK_WALL:
  313. targetLoc = world.get_loc(targetXLoc, targetYLoc);
  314. if(targetLoc->wall_nation_recno()==nationRecno1 || targetLoc->wall_nation_recno()==nationRecno2)
  315. unitPtr->stop2(KEEP_DEFENSE_MODE);
  316. break;
  317. }
  318. }
  319. }
  320. }
  321. //----------- End of function UnitArray::stop_war_between -----------//
  322. //--------- Begin of function UnitArray::stop_attack_unit ---------//
  323. // stop all units that is attacking the specified unit
  324. //
  325. // <short> unitRecno - unit_recno of the specified unit
  326. //
  327. void UnitArray::stop_attack_unit(short unitRecno)
  328. {
  329. if(nation_hand_over_flag)
  330. return;
  331. Unit *unitPtr;
  332. for(int i=size(); i>0; --i)
  333. {
  334. if(is_deleted(i))
  335. continue;
  336. unitPtr = operator[](i);
  337. if(!unitPtr->is_visible())
  338. continue;
  339. if((unitPtr->action_para==unitRecno && unitPtr->action_mode==ACTION_ATTACK_UNIT) ||
  340. (unitPtr->action_para2==unitRecno && unitPtr->action_mode2==ACTION_ATTACK_UNIT))
  341. unitPtr->stop2(KEEP_DEFENSE_MODE);
  342. }
  343. }
  344. //----------- End of function UnitArray::stop_attack_unit -----------//
  345. //--------- Begin of function UnitArray::stop_attack_firm ---------//
  346. // stop all units that is attacking the specified firm
  347. //
  348. // <short> firmRecno - the firm_recno of the firm
  349. //
  350. void UnitArray::stop_attack_firm(short firmRecno)
  351. {
  352. if(nation_hand_over_flag)
  353. return;
  354. Unit *unitPtr;
  355. for(int i=size(); i>0; --i)
  356. {
  357. if(is_deleted(i))
  358. continue;
  359. unitPtr = operator[](i);
  360. if(!unitPtr->is_visible())
  361. continue;
  362. if((unitPtr->action_para==firmRecno && unitPtr->action_mode==ACTION_ATTACK_FIRM) ||
  363. (unitPtr->action_para2==firmRecno && unitPtr->action_mode2==ACTION_ATTACK_FIRM))
  364. unitPtr->stop2(KEEP_DEFENSE_MODE);
  365. }
  366. }
  367. //----------- End of function UnitArray::stop_attack_firm -----------//
  368. //--------- Begin of function UnitArray::stop_attack_town ---------//
  369. // stop all units that is attacking the specified town
  370. //
  371. // <short> townRecno - the town_recno of the specified town
  372. //
  373. void UnitArray::stop_attack_town(short townRecno)
  374. {
  375. if(nation_hand_over_flag)
  376. return;
  377. Unit *unitPtr;
  378. for(int i=size(); i>0; --i)
  379. {
  380. if(is_deleted(i))
  381. continue;
  382. unitPtr = operator[](i);
  383. if(!unitPtr->is_visible())
  384. continue;
  385. if((unitPtr->action_para==townRecno && unitPtr->action_mode==ACTION_ATTACK_TOWN) ||
  386. (unitPtr->action_para2==townRecno && unitPtr->action_mode2==ACTION_ATTACK_TOWN))
  387. unitPtr->stop2(KEEP_DEFENSE_MODE);
  388. }
  389. }
  390. //----------- End of function UnitArray::stop_attack_town -----------//
  391. //--------- Begin of function UnitArray::assign ---------//
  392. // group assign to firm/town/unit
  393. //
  394. // <int> destX - x location assigned to
  395. // <int> destY - y location assigned to
  396. // <int> divided - whether the array is divied by divide_array(...) (1 - divided, 0 not)
  397. // <char> remoteAction -
  398. // [short*] selectedArray - unit_recno of the selected units (default: NULL)
  399. // [int] selectedCount - number of selected units (default: 0)
  400. //
  401. void UnitArray::assign(int destX, int destY, int divided, char remoteAction, short* selectedArray, int selectedCount)
  402. {
  403. err_when(destX<0 || destY<0 || destX>MAX_WORLD_X_LOC-1 || destY>MAX_WORLD_Y_LOC-1);
  404. //###### begin trevor 25/8 #######//
  405. //--- set the destination to the top left position of the town/firm ---//
  406. Location* locPtr = world.get_loc(destX, destY);
  407. //---- if there is a firm on this location -----//
  408. if( locPtr->is_firm() )
  409. {
  410. Firm* firmPtr = firm_array[locPtr->firm_recno()];
  411. destX = firmPtr->loc_x1;
  412. destY = firmPtr->loc_y1;
  413. }
  414. //---- if there is a town on this location -----//
  415. else if( locPtr->is_town() )
  416. {
  417. Town* townPtr = town_array[locPtr->town_recno()];
  418. destX = townPtr->loc_x1;
  419. destY = townPtr->loc_y1;
  420. }
  421. //###### end trevor 25/8 #######//
  422. //-------------------------------------------//
  423. Unit* unitPtr;
  424. int freeMemory = 0;
  425. if( selectedArray == NULL)
  426. {
  427. selectedArray = (short*) mem_add(sizeof(short)*size());
  428. selectedCount = 0;
  429. freeMemory = 1;
  430. // find myself
  431. for(int i=size(); i>0; i--)
  432. {
  433. if(is_deleted(i))
  434. continue;
  435. unitPtr = operator[](i);
  436. //err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0);
  437. if(!unitPtr->is_visible())
  438. continue;
  439. if( unitPtr->selected_flag && unitPtr->is_own() )
  440. {
  441. err_when(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE);
  442. selectedArray[selectedCount++] = i;
  443. }
  444. }
  445. }
  446. if(!remoteAction && remote.is_enable())
  447. {
  448. // packet structure : <xLoc> <yLoc> <no. of units> <unit recno ...>
  449. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_ASSIGN,
  450. sizeof(short) * (4+selectedCount));
  451. shortPtr[0] = destX;
  452. shortPtr[1] = destY;
  453. shortPtr[2] = selectedCount;
  454. shortPtr[3] = divided;
  455. memcpy(shortPtr+4, selectedArray, sizeof(short)*selectedCount);
  456. }
  457. else
  458. {
  459. if(!divided)
  460. {
  461. for(int j=0; j< selectedCount; ++j)
  462. {
  463. int i = selectedArray[j];
  464. if(is_deleted(i))
  465. continue;
  466. unitPtr = operator[](i); //unit_array[i];
  467. //### begin trevor 7/7#######//
  468. err_when(!unitPtr->is_visible() );
  469. err_when( unitPtr->hit_points<=0 );
  470. //### end trevor 7/7#######//
  471. unitPtr->stop2();
  472. }
  473. //--------- divide the unit by their mobile_type ------------//
  474. divide_array(destX, destY, selectedArray, selectedCount);
  475. if(selected_land_unit_count)
  476. assign(destX, destY, 1, remoteAction, selected_land_unit_array, selected_land_unit_count);
  477. if(selected_sea_unit_count)
  478. {
  479. Location *locPtr = world.get_loc(destX, destY);
  480. if(locPtr->is_firm())
  481. {
  482. err_when(firm_array.is_deleted(locPtr->firm_recno()));
  483. Firm *firmPtr = firm_array[locPtr->firm_recno()];
  484. if(firmPtr->firm_id==FIRM_HARBOR) // recursive call
  485. assign(destX, destY, 1, remoteAction, selected_sea_unit_array, selected_sea_unit_count);
  486. else
  487. ship_to_beach(destX, destY, 1, selected_sea_unit_array, selected_sea_unit_count, remoteAction);
  488. }
  489. //else if(locPtr->is_town())
  490. else
  491. {
  492. err_when(town_array.is_deleted(locPtr->town_recno()));
  493. ship_to_beach(destX, destY, 1, selected_sea_unit_array, selected_sea_unit_count, remoteAction);
  494. }
  495. }
  496. if(selected_air_unit_count) // no assign for air units
  497. move_to(destX, destY, 1, selected_air_unit_array, selected_air_unit_count, remoteAction);
  498. //------------ deinit static variables ------------//
  499. selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0;
  500. mem_del(selected_land_unit_array);
  501. mem_del(selected_sea_unit_array);
  502. mem_del(selected_air_unit_array);
  503. }
  504. else
  505. {
  506. //---------- set unit to assign -----------//
  507. if(selectedCount<2)
  508. {
  509. unitPtr = (Unit*) get_ptr(selectedArray[0]);
  510. err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0);
  511. if(unitPtr->sprite_info->loc_width<=1)
  512. {
  513. unitPtr->unit_group_id = unit_array.cur_group_id++;
  514. unitPtr->assign(destX, destY);
  515. }
  516. else // move to object surrounding
  517. {
  518. Location *locPtr = world.get_loc(destX, destY);
  519. if(locPtr->is_firm())
  520. unitPtr->move_to_firm_surround(destX, destY, unitPtr->sprite_info->loc_width, unitPtr->sprite_info->loc_height, locPtr->firm_recno());
  521. else if(locPtr->is_town())
  522. unitPtr->move_to_town_surround(destX, destY, unitPtr->sprite_info->loc_width, unitPtr->sprite_info->loc_height);
  523. else if(locPtr->has_unit(UNIT_LAND))
  524. unitPtr->move_to_unit_surround(destX, destY, unitPtr->sprite_info->loc_width, unitPtr->sprite_info->loc_height, locPtr->unit_recno(UNIT_LAND));
  525. }
  526. }
  527. else // for more than one unit selecting, call group_assign() to take care of it
  528. {
  529. set_group_id(selectedArray, selectedCount);
  530. group_assign(destX, destY, selectedArray, selectedCount);
  531. }
  532. }
  533. }
  534. if( freeMemory )
  535. mem_del(selectedArray);
  536. }
  537. //----------- End of function UnitArray::assign -----------//
  538. //--------- Begin of function UnitArray::group_assign ---------//
  539. // <int> destX - x location assigned to
  540. // <int> destY - y location assigned to
  541. // <short*> selectedArray - unit recno of the selected units
  542. // <int> selectedCount - num of selected units
  543. //
  544. void UnitArray::group_assign(int destX, int destY, short* selectedArray, int selectedCount)
  545. {
  546. enum { ASSIGN_TYPE_UNIT = 1,
  547. ASSIGN_TYPE_FIRM,
  548. ASSIGN_TYPE_TOWN,
  549. };
  550. Location *locPtr = world.get_loc(destX, destY);
  551. int assignType = 0; // 1 for unit, 2 for firm, 3 for town
  552. int miscNo = 0; // usedd to store the recno of the object
  553. if(locPtr->has_unit(UNIT_LAND))
  554. {
  555. assignType = ASSIGN_TYPE_UNIT;
  556. miscNo = locPtr->unit_recno(UNIT_LAND);
  557. }
  558. else if(locPtr->is_firm())
  559. {
  560. assignType = ASSIGN_TYPE_FIRM;
  561. miscNo = firm_array[locPtr->firm_recno()]->firm_id;
  562. }
  563. else if(locPtr->is_town())
  564. {
  565. assignType = ASSIGN_TYPE_TOWN;
  566. miscNo = 0;
  567. }
  568. else
  569. err_here();
  570. Unit* unitPtr;
  571. for(int i=0; i<selectedCount; i++)
  572. {
  573. unitPtr = operator[](selectedArray[i]);
  574. err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0);
  575. if(unitPtr->sprite_info->loc_width<=1)
  576. unitPtr->assign(destX, destY, i+1); // the thrid parameter is used to generate different result for the searching
  577. else
  578. {
  579. //-----------------------------------------------------------------//
  580. // for 2x2 unit, unable to assign, so move to the surrounding
  581. //-----------------------------------------------------------------//
  582. switch(assignType)
  583. {
  584. case ASSIGN_TYPE_UNIT:
  585. unitPtr->move_to_unit_surround(destX, destY, unitPtr->sprite_info->loc_width,
  586. unitPtr->sprite_info->loc_height, miscNo);
  587. break; // is a unit
  588. case ASSIGN_TYPE_FIRM:
  589. unitPtr->move_to_firm_surround(destX, destY, unitPtr->sprite_info->loc_width,
  590. unitPtr->sprite_info->loc_height, miscNo);
  591. break; // is a firm
  592. case ASSIGN_TYPE_TOWN:
  593. unitPtr->move_to_town_surround(destX, destY, unitPtr->sprite_info->loc_width,
  594. unitPtr->sprite_info->loc_height);
  595. break; // is a town
  596. default: err_here();
  597. break;
  598. }
  599. }
  600. }
  601. }
  602. //----------- End of function UnitArray::group_assign -----------//
  603. //--------- Begin of function UnitArray::assign_to_camp ---------//
  604. // <int> destX - x location where the camp is
  605. // <int> destY - y location where the camp is
  606. // <char> remoteAction -
  607. // [short*] selectedUnitArray - recno of the selected units (default: NULL)
  608. // [int] selectedCount - number of selected units (default: 0)
  609. //
  610. void UnitArray::assign_to_camp(int destX, int destY, char remoteAction, short* selectedUnitArray, int selectedCount)
  611. {
  612. divide_array(destX, destY, selectedUnitArray, selectedCount);
  613. if(selected_land_unit_count)
  614. {
  615. int assignCount=0, moveCount=0;
  616. short *assignArray = (short*) mem_add(sizeof(short)*selected_land_unit_count);
  617. short *moveArray = (short*) mem_add(sizeof(short)*selected_land_unit_count);
  618. char unitClass;
  619. Unit *unitPtr;
  620. memset(assignArray, 0, sizeof(short)*selected_land_unit_count);
  621. memset(moveArray, 0, sizeof(short)*selected_land_unit_count);
  622. //----------------------------------------------------------------//
  623. // Only human and weapon can be assigned to the camp. Others are
  624. // ordered to move to camp as close as possible.
  625. //----------------------------------------------------------------//
  626. for(int i=0; i<selectedCount; i++)
  627. {
  628. err_when(unit_array.is_deleted(selectedUnitArray[i]));
  629. unitPtr = operator[](selectedUnitArray[i]);
  630. unitClass = unit_res[unitPtr->unit_id]->unit_class;
  631. if(unitClass==UNIT_CLASS_HUMAN || unitClass==UNIT_CLASS_WEAPON)
  632. assignArray[assignCount++] = selectedUnitArray[i];
  633. else
  634. moveArray[moveCount++] = selectedUnitArray[i];
  635. }
  636. if(assignCount)
  637. assign(destX, destY, 1, remoteAction, assignArray, assignCount);
  638. if(moveCount)
  639. move_to(destX, destY, 1, moveArray, moveCount, remoteAction);
  640. mem_del(assignArray);
  641. mem_del(moveArray);
  642. }
  643. if(selected_sea_unit_count)
  644. ship_to_beach(destX, destY, 1, selected_sea_unit_array, selected_sea_unit_count, remoteAction);
  645. if(selected_air_unit_count)
  646. move_to(destX, destY, 1, selected_air_unit_array, selected_air_unit_count, remoteAction);
  647. //---------------- deinit static parameters ---------------//
  648. selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0;
  649. mem_del(selected_land_unit_array);
  650. mem_del(selected_sea_unit_array);
  651. mem_del(selected_air_unit_array);
  652. }
  653. //----------- End of function UnitArray::assign_to_camp -----------//
  654. //--------- Begin of function UnitArray::settle ---------//
  655. // <int> destX - x location settle to
  656. // <int> destY - y location settle to
  657. // <int> divided - whether the selected is divided into subgroup, (1 = divided, 0 = not)
  658. // <char> remoteAction -
  659. // [short*] selectedArray - the recno of the selected units (default: NULL)
  660. // [int] selectedCount - num of selected units (default: 0)
  661. //
  662. void UnitArray::settle(int destX, int destY, int divided, char remoteAction, short* selectedArray, int selectedCount)
  663. {
  664. Unit* unitPtr;
  665. int freeMemory = 0;
  666. if(selectedArray == NULL)
  667. {
  668. selectedArray = (short*) mem_add(sizeof(short)*size());
  669. selectedCount = 0;
  670. freeMemory = 1;
  671. // find myself
  672. for(int i=size(); i>0; i--)
  673. {
  674. if(is_deleted(i))
  675. continue;
  676. unitPtr = operator[](i);
  677. //err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0);
  678. if(!unitPtr->is_visible())
  679. continue;
  680. if( unitPtr->selected_flag && unitPtr->is_own() )
  681. {
  682. err_when(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE);
  683. selectedArray[selectedCount++] = i;
  684. }
  685. }
  686. }
  687. if(!remoteAction && remote.is_enable())
  688. {
  689. // packet structure : <xLoc> <yLoc> <no. of units> <divided> <unit recno ...>
  690. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNITS_SETTLE, sizeof(short)*(4+selectedCount));
  691. shortPtr[0] = destX;
  692. shortPtr[1] = destY;
  693. shortPtr[2] = selectedCount;
  694. shortPtr[3] = divided;
  695. memcpy(shortPtr+4, selectedArray, sizeof(short)*selectedCount);
  696. }
  697. else
  698. {
  699. if(!divided)
  700. {
  701. for(int j=0; j< selectedCount; ++j)
  702. {
  703. int i = selectedArray[j];
  704. if(is_deleted(i))
  705. continue;
  706. unitPtr = operator[](i); //unit_array[i];
  707. err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0);
  708. unitPtr->stop2();
  709. }
  710. divide_array(destX, destY, selectedArray, selectedCount);
  711. if(selected_land_unit_count)
  712. settle(destX, destY, 1, remoteAction, selected_land_unit_array, selected_land_unit_count);
  713. if(selected_sea_unit_count)
  714. ship_to_beach(destX, destY, 1, selected_sea_unit_array, selected_sea_unit_count, remoteAction);
  715. if(selected_air_unit_count)
  716. move_to(destX, destY, 1, selected_air_unit_array, selected_air_unit_count, remoteAction);
  717. //-------------- deinit static parameters --------------//
  718. selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0;
  719. mem_del(selected_land_unit_array);
  720. mem_del(selected_sea_unit_array);
  721. mem_del(selected_air_unit_array);
  722. }
  723. else
  724. {
  725. //---------- set unit to settle -----------//
  726. if(selectedCount<2)
  727. {
  728. unitPtr = (Unit*) get_ptr(selectedArray[0]);
  729. err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0);
  730. unitPtr->unit_group_id = unit_array.cur_group_id++;
  731. unitPtr->settle(destX, destY);
  732. }
  733. else
  734. {
  735. set_group_id(selectedArray, selectedCount);
  736. group_settle(destX, destY, selectedArray, selectedCount);
  737. }
  738. }
  739. }
  740. if(freeMemory)
  741. mem_del(selectedArray);
  742. }
  743. //----------- End of function UnitArray::settle -----------//
  744. //--------- Begin of function UnitArray::group_settle ---------//
  745. // <int> destX - x location to settle to
  746. // <int> destY - y location to settle to
  747. // <short*> selectedArray - recno. of selected units
  748. // <int> selectedCount - num. of selected units
  749. //
  750. void UnitArray::group_settle(int destX, int destY, short* selectedArray, int selectedCount)
  751. {
  752. #ifdef DEBUG
  753. DWORD debugGroupId = (operator[](selectedArray[0]))->unit_group_id;
  754. #endif
  755. Unit* unitPtr;
  756. for(int i=0; i<selectedCount; i++)
  757. {
  758. unitPtr = operator[](selectedArray[i]);
  759. err_when(!unitPtr->is_visible() || unitPtr->hit_points<=0);
  760. #ifdef DEBUG
  761. err_when(unitPtr->unit_group_id!=debugGroupId);
  762. #endif
  763. unitPtr->settle(destX, destY, i+1);
  764. }
  765. }
  766. //----------- End of function UnitArray::group_settle -----------//
  767. //--------- Begin of function UnitArray::assign_to_ship ---------//
  768. // <int> shipXLoc - x location of the ship
  769. // <int> shipYLoc - y location of the ship
  770. // <int> divided - whether the selected groups is divided (1 - divided, 0 - not)
  771. // <short*> selectedArray - recno of selected units
  772. // <int> selectedCount - num. of selected units
  773. // <char> remoteAction -
  774. //
  775. void UnitArray::assign_to_ship(int shipXLoc, int shipYLoc, int divided, short* selectedArray, int selectedCount, char remoteAction, int shipRecno)
  776. {
  777. err_when(terrain_res[world.get_loc(shipXLoc, shipYLoc)->terrain_id]->average_type!=TERRAIN_OCEAN);
  778. err_when(!selectedCount || selectedCount>1000);
  779. if( !remoteAction && remote.is_enable() )
  780. {
  781. // packet structure : <xLoc> <yLoc> <ship recno> <no. of units> <divided> <unit recno ...>
  782. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNITS_ASSIGN_TO_SHIP,
  783. sizeof(short) * (5+selectedCount));
  784. shortPtr[0] = shipXLoc;
  785. shortPtr[1] = shipYLoc;
  786. shortPtr[2] = shipRecno;
  787. shortPtr[3] = selectedCount;
  788. shortPtr[4] = divided;
  789. memcpy(shortPtr+5, selectedArray, sizeof(short)*selectedCount);
  790. return;
  791. }
  792. if(!divided)
  793. {
  794. divide_array(shipXLoc, shipYLoc, selectedArray, selectedCount);
  795. if(selected_sea_unit_count) // Note: the order to call ship unit first
  796. move_to(shipXLoc, shipYLoc, 1, selected_sea_unit_array, selected_sea_unit_count, remoteAction);
  797. if(selected_land_unit_count)
  798. assign_to_ship(shipXLoc, shipYLoc, 1, selected_land_unit_array, selected_land_unit_count, remoteAction, shipRecno);
  799. if(selected_air_unit_count)
  800. move_to(shipXLoc, shipYLoc, 1, selected_air_unit_array, selected_air_unit_count, remoteAction);
  801. //---------------- deinit static parameters -----------------//
  802. selected_land_unit_count = selected_sea_unit_count = selected_air_unit_count = 0;
  803. mem_del(selected_land_unit_array);
  804. mem_del(selected_sea_unit_array);
  805. mem_del(selected_air_unit_array);
  806. return;
  807. }
  808. else
  809. {
  810. // ###### begin Gilbert 5/8 ##########//
  811. // ----- dont not use shipXLoc, shipYLoc passed, use shipRecno --------//
  812. UnitMarine *shipPtr = (UnitMarine*) get_ptr(shipRecno);
  813. if( shipPtr && shipPtr->is_visible() )
  814. {
  815. shipXLoc = shipPtr->next_x_loc();
  816. shipYLoc = shipPtr->next_y_loc();
  817. }
  818. else
  819. return;
  820. // ##### patch end Gilbert 5/8 #######//
  821. //------------------------------------------------------------------------------------//
  822. // find the closest unit to the ship
  823. //------------------------------------------------------------------------------------//
  824. int minDist=0x7FFFFF, dist, distX, distY;
  825. int closestUnitRecno = -1;
  826. Unit *unitPtr;
  827. int i;
  828. for(i=0; i<selectedCount; i++)
  829. {
  830. unitPtr = (Unit*) get_ptr(selectedArray[i]);
  831. distX = abs(shipXLoc - unitPtr->next_x_loc());
  832. distY = abs(shipYLoc - unitPtr->next_y_loc());
  833. dist = (distX>distY) ? distX : distY;
  834. if(dist < minDist)
  835. {
  836. minDist = dist;
  837. closestUnitRecno = i;
  838. }
  839. }
  840. err_when(closestUnitRecno==-1);
  841. //------------------------------------------------------------------------------------//
  842. // If the seleceted units are distributed on different territories, select those unit
  843. // on the same territory as the closet unit for processing, there will be no action for
  844. // the rest units.
  845. //------------------------------------------------------------------------------------//
  846. DWORD curGroupId = unit_array.cur_group_id++;
  847. Unit *closestUnit = (Unit*) get_ptr(selectedArray[closestUnitRecno]);
  848. int closestUnitXLoc = closestUnit->next_x_loc();
  849. int closestUnitYLoc = closestUnit->next_y_loc();
  850. unsigned char defaultRegionId = world.get_loc(closestUnitXLoc, closestUnitYLoc)->region_id;
  851. short *newSelectedArray;
  852. int newSelectedCount = 0;
  853. if(selectedCount>1)
  854. {
  855. newSelectedArray = (short*) mem_add(sizeof(short)*selectedCount);
  856. memset(newSelectedArray, 0, sizeof(short)*selectedCount);
  857. for(i=0; i<selectedCount; i++)
  858. {
  859. unitPtr = (Unit*) get_ptr(selectedArray[i]);
  860. if(world.get_loc(unitPtr->next_x_loc(), unitPtr->next_y_loc())->region_id == defaultRegionId)
  861. {
  862. newSelectedArray[newSelectedCount++] = selectedArray[i]; // on the same territory
  863. unitPtr->unit_group_id = curGroupId;
  864. }
  865. if(unitPtr->cur_action==SPRITE_IDLE)
  866. unitPtr->set_ready();
  867. }
  868. err_when(newSelectedCount > selectedCount);
  869. }
  870. else
  871. {
  872. err_when(closestUnit->sprite_recno!=selectedArray[0]);
  873. newSelectedArray = (short*) mem_add(sizeof(short)); // only one unit
  874. newSelectedArray[0] = selectedArray[0];
  875. newSelectedCount = 1;
  876. closestUnit->unit_group_id = curGroupId;
  877. }
  878. //-------------- ordering the ship move near the coast ----------------//
  879. int curXLoc = closestUnit->next_x_loc();
  880. int curYLoc = closestUnit->next_y_loc();
  881. // ##### patch begin Gilbert 5/8 #######//
  882. // UnitMarine *shipPtr = (UnitMarine*) get_ptr(world.get_unit_recno(shipXLoc, shipYLoc, UNIT_SEA));
  883. // ##### patch end Gilbert 5/8 #######//
  884. int landX, landY;
  885. shipPtr->unit_group_id = curGroupId;
  886. shipPtr->ship_to_beach(curXLoc, curYLoc, landX, landY);
  887. if(landX!=-1 && landY!=-1)
  888. {
  889. //-------------- ordering the units ---------------//
  890. #define TRY_SIZE 5
  891. int countLimit = TRY_SIZE*TRY_SIZE;
  892. //### begin alex 30/10 ###//
  893. int j, k, xShift, yShift, checkXLoc, checkYLoc;
  894. UCHAR regionId = world.get_loc(landX, landY)->region_id;
  895. Location *locPtr;
  896. for(i=0, k=0; i<newSelectedCount; i++)
  897. {
  898. for(j=1; j<countLimit; j++)
  899. {
  900. if(++k>countLimit)
  901. k = 1;
  902. m.cal_move_around_a_point(k, TRY_SIZE, TRY_SIZE, xShift, yShift);
  903. checkXLoc = landX+xShift;
  904. checkYLoc = landY+yShift;
  905. if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
  906. continue;
  907. locPtr = world.get_loc(checkXLoc, checkYLoc);
  908. if(locPtr->region_id!=regionId || !locPtr->can_move(UNIT_LAND))
  909. continue;
  910. unitPtr = (Unit*) get_ptr(newSelectedArray[i]);
  911. unitPtr->assign_to_ship(landX, landY, shipPtr->sprite_recno, k);
  912. break;
  913. }
  914. }
  915. //#### end alex 30/10 ####//
  916. }
  917. mem_del(newSelectedArray);
  918. }
  919. }
  920. //----------- End of function UnitArray::assign_to_ship -----------//
  921. //--------- Begin of function UnitArray::ship_to_beach ---------//
  922. // <int> destX - x location the ship move to
  923. // <int> destY - y location the ship move to
  924. // <int> divided - whether the units are divided (1 - divided, 0 - not)
  925. // <short*> selectedArray - the recno. of the selected units
  926. // <int> selectedCount - num. of selected units
  927. // <char> remoteAction -
  928. //
  929. void UnitArray::ship_to_beach(int destX, int destY, int divided, short* selectedArray, int selectedCount, char remoteAction)
  930. {
  931. Unit *unitPtr;
  932. if( !remoteAction && remote.is_enable() )
  933. {
  934. // packet structure : <xLoc> <yLoc> <no. of units> <divided> <unit recno ...>
  935. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNITS_SHIP_TO_BEACH,
  936. sizeof(short) * (4+selectedCount));
  937. shortPtr[0] = destX;
  938. shortPtr[1] = destY;
  939. shortPtr[2] = selectedCount;
  940. shortPtr[3] = divided;
  941. memcpy(shortPtr+4, selectedArray, sizeof(short)*selectedCount);
  942. return;
  943. }
  944. set_group_id(selectedArray, selectedCount);
  945. //--------------------------------------------------------------------//
  946. //--------------------------------------------------------------------//
  947. #define CHECK_SEA_DIMENSION 50
  948. #define CHECK_SEA_SIZE CHECK_SEA_DIMENSION*CHECK_SEA_DIMENSION
  949. Location *locPtr = world.get_loc(destX, destY);
  950. UCHAR regionId = locPtr->region_id;
  951. int xShift, yShift, checkXLoc, checkYLoc;
  952. int landX, landY, seaX, seaY, tempX, tempY;
  953. int j=1, k, found;
  954. //--------------------------------------------------------------------//
  955. // find a unit that can carrying units. Let it to do the first searching.
  956. // Use the returned reference parameters (landX, landY) for the other
  957. // ships to calculate their final location to move to
  958. //--------------------------------------------------------------------//
  959. int i;
  960. for(i=0; i<selectedCount; i++) // for first unit
  961. {
  962. unitPtr = (Unit*) get_ptr(selectedArray[i]);
  963. if(unit_res[unitPtr->unit_id]->carry_unit_capacity>0)
  964. {
  965. unitPtr->ship_to_beach(destX, destY, landX, landY); // landX=landY=-1 if calling move_to() instead
  966. i++;
  967. break;
  968. }
  969. else
  970. unitPtr->move_to(destX, destY, 1);
  971. }
  972. int totalCheck = 0;
  973. for(; i<selectedCount; i++) // for the rest units
  974. {
  975. unitPtr = (Unit*) get_ptr(selectedArray[i]);
  976. if(unit_res[unitPtr->unit_id]->carry_unit_capacity>0 && landX!=-1 && landY!=-1)
  977. {
  978. for(found=0; j<=CHECK_SEA_SIZE; j++, totalCheck++)
  979. {
  980. m.cal_move_around_a_point(j, CHECK_SEA_DIMENSION, CHECK_SEA_DIMENSION, xShift, yShift);
  981. if(j>=CHECK_SEA_SIZE)
  982. j = 1;
  983. if(totalCheck == CHECK_SEA_SIZE)
  984. {
  985. //--------------------------------------------------------------------//
  986. // can't handle this case
  987. //--------------------------------------------------------------------//
  988. unitPtr->ship_to_beach(landX, landY, tempX, tempY);
  989. totalCheck = 0;
  990. break;
  991. }
  992. seaX = landX+xShift;
  993. seaY = landY+yShift;
  994. if(seaX<0 || seaX>=MAX_WORLD_X_LOC || seaY<0 || seaY>=MAX_WORLD_Y_LOC)
  995. continue;
  996. locPtr = world.get_loc(seaX, seaY);
  997. if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN)
  998. continue;
  999. //--------------------------------------------------------------------//
  1000. // if it is able to find a location around the surrounding location with
  1001. // same region id we prefer, order the unit to move there.
  1002. //--------------------------------------------------------------------//
  1003. for(k=2; k<=9; k++)
  1004. {
  1005. m.cal_move_around_a_point(k, 3, 3, xShift, yShift);
  1006. checkXLoc = seaX+xShift;
  1007. checkYLoc = seaY+yShift;
  1008. if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
  1009. continue;
  1010. locPtr = world.get_loc(checkXLoc, checkYLoc);
  1011. if(locPtr->region_id!=regionId)
  1012. continue;
  1013. unitPtr->ship_to_beach(checkXLoc, checkYLoc, tempX, tempY);
  1014. found++;
  1015. err_when(unitPtr->result_node_array && unitPtr->result_node_count==unitPtr->result_node_recno &&
  1016. (unitPtr->result_node_array[unitPtr->result_node_count-1].node_x!=unitPtr->go_x>>ZOOM_X_SHIFT_COUNT ||
  1017. unitPtr->result_node_array[unitPtr->result_node_count-1].node_y!=unitPtr->go_y>>ZOOM_Y_SHIFT_COUNT));
  1018. break;
  1019. }
  1020. if(found)
  1021. {
  1022. totalCheck = 0;
  1023. break;
  1024. }
  1025. }
  1026. }
  1027. else // cannot carry units
  1028. unitPtr->move_to(destX, destY, 1);
  1029. }
  1030. }
  1031. //----------- End of function UnitArray::ship_to_beach -----------//
  1032. //----------- Begin of function UnitArray::divide_attack_by_nation -----------//
  1033. //
  1034. // units which can be controlled by nationRecno to attack are moved
  1035. // to the front of the selectedArray, return is number of units passed
  1036. //
  1037. int UnitArray::divide_attack_by_nation(short nationRecno, short *selectedArray, int selectedCount)
  1038. {
  1039. // elements before i are pass, elements on or after passCount are not pass
  1040. int loopCount = selectedCount+2;
  1041. int passCount = selectedCount;
  1042. for( int i = 0; i < passCount; )
  1043. {
  1044. err_when(--loopCount == 0);
  1045. short unitRecno = selectedArray[i];
  1046. // a clocked spy cannot be commanded by original nation to attack
  1047. if( !is_deleted(unitRecno) && operator[](unitRecno)->nation_recno == nationRecno )
  1048. {
  1049. // pass
  1050. ++i;
  1051. }
  1052. else
  1053. {
  1054. // fail, swap [i] with [passCount-1]
  1055. --passCount;
  1056. selectedArray[i] = selectedArray[passCount];
  1057. selectedArray[passCount] = unitRecno;
  1058. }
  1059. }
  1060. return passCount;
  1061. }
  1062. //----------- End of function UnitArray::divide_attack_by_nation -----------//
  1063. //----------- Begin of function UnitArray::add_way_point -----------//
  1064. // <int> pointX - x location of the point to be added
  1065. // <int> pointY - y location of the point to be added
  1066. // <short*> selectedArray - recno. of selected units
  1067. // <int> selectedCount - num. of selected units
  1068. // <char> remoteAction -
  1069. //
  1070. void UnitArray::add_way_point(int pointX, int pointY, short* selectedArray, int selectedCount, char remoteAction)
  1071. {
  1072. if(!remoteAction && remote.is_enable())
  1073. {
  1074. // packet structure : <xLoc> <yLoc> <no. of units> <unit recno ...>
  1075. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_ADD_WAY_POINT,
  1076. sizeof(short) * (3+selectedCount));
  1077. shortPtr[0] = pointX;
  1078. shortPtr[1] = pointY;
  1079. shortPtr[2] = selectedCount;
  1080. memcpy(shortPtr+3, selectedArray, sizeof(short)*selectedCount);
  1081. }
  1082. else
  1083. {
  1084. DWORD groupId = unit_array.cur_group_id;
  1085. Unit *unitPtr;
  1086. int i;
  1087. for(i=0; i<selectedCount; ++i)
  1088. {
  1089. unitPtr = unit_array[selectedArray[i]];
  1090. unitPtr->unit_group_id = groupId;
  1091. }
  1092. unit_array.cur_group_id++;
  1093. for(i=0; i<selectedCount; ++i)
  1094. {
  1095. unitPtr = unit_array[selectedArray[i]];
  1096. unitPtr->add_way_point(pointX, pointY);
  1097. }
  1098. }
  1099. }
  1100. //----------- End of function UnitArray::add_way_point -----------//