OUNITA.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  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 : OUNITA.CPP
  21. //Description : Object UnitArray
  22. #include <ALL.h>
  23. #include <OVGA.h>
  24. #include <OSYS.h>
  25. #include <OSTR.h>
  26. #include <OSPY.h>
  27. #include <OREMOTE.h>
  28. #include <ONATION.h>
  29. #include <OREBEL.h>
  30. #include <OGODRES.h>
  31. #include <OUNITALL.h>
  32. #include <OWORLD.h>
  33. #include <OCONFIG.h>
  34. #include <OGAME.h>
  35. #include <OANLINE.h>
  36. #include <OFONT.h>
  37. #include <CRC.h>
  38. #ifdef NO_DEBUG_UNIT
  39. #undef err_when
  40. #undef err_here
  41. #undef err_if
  42. #undef err_else
  43. #undef err_now
  44. #define err_when(cond)
  45. #define err_here()
  46. #define err_if(cond)
  47. #define err_else
  48. #define err_now(msg)
  49. #undef DEBUG
  50. #endif
  51. //--------- Declare static functions ---------//
  52. static void put_profile(int y, char* dispDes, int dispValue);
  53. //--------- Begin of function UnitArray::UnitArray ---------//
  54. //
  55. // <int> initArraySize - the initial size of this array.
  56. //
  57. UnitArray::UnitArray(int initArraySize) : SpriteArray(initArraySize)
  58. {
  59. }
  60. //----------- End of function UnitArray::UnitArray -----------//
  61. //--------- Begin of function UnitArray::init ---------//
  62. //
  63. void UnitArray::init()
  64. {
  65. //-------- initialize group selection parameter -------//
  66. cur_group_id = 1;
  67. cur_team_id = 1;
  68. selected_land_unit_count = 0;
  69. selected_sea_unit_count = 0;
  70. selected_air_unit_count = 0;
  71. idle_blocked_unit_reset_count = 0;
  72. selected_land_unit_array = NULL;
  73. selected_sea_unit_array = NULL;
  74. selected_air_unit_array = NULL;
  75. visible_unit_count = 0;
  76. mp_first_frame_to_select_caravan = 0;
  77. mp_first_frame_to_select_ship = 0;
  78. mp_pre_selected_caravan_recno = 0;
  79. mp_pre_selected_ship_recno = 0;
  80. //------------ init sprite_array ------------//
  81. SpriteArray::init();
  82. }
  83. //----------- End of function UnitArray::init -----------//
  84. //--------- Begin of function UnitArray::add_unit ---------//
  85. //
  86. // <int> unitId - the id. of the unit
  87. // <int> nationRecno - the recno of the nation that the unit belongs to
  88. // [int] rankId - rank id. of the unit (none for non-human unit)
  89. // [int] unitLoyalty - loyalty of the unit (none for non-human unit)
  90. // [int] startXLoc, startYLoc - the starting location of the unit
  91. // (if startXLoc < 0, this is a unit for hire, and is not a unit of the game yet. init_sprite() won't be called for this unit)
  92. // (default: -1, -1)
  93. // [int] remoteAction - whether this is a remote action or not.
  94. //
  95. // return : <int> - the recno of the unit added.
  96. //
  97. int UnitArray::add_unit(int unitId, int nationRecno, int rankId, int unitLoyalty, int startXLoc, int startYLoc)
  98. {
  99. //-------- create and initialize Unit -------//
  100. Unit* unitPtr = create_unit(unitId);
  101. //----------- add to SpriteArray ------------//
  102. unitPtr->init(unitId, nationRecno, rankId, unitLoyalty, startXLoc, startYLoc);
  103. //-------------------------------------------//
  104. return unitPtr->sprite_recno;
  105. }
  106. //----------- End of function UnitArray::add_unit -----------//
  107. //-------- Begin of function UnitArray::create_unit --------//
  108. //
  109. Unit* UnitArray::create_unit(int unitId)
  110. {
  111. Unit* unitPtr;
  112. UnitInfo* unitInfo = unit_res[unitId];
  113. switch(unitId)
  114. {
  115. case UNIT_CARAVAN:
  116. unitPtr = new UnitCaravan;
  117. break;
  118. case UNIT_VESSEL:
  119. case UNIT_TRANSPORT:
  120. case UNIT_CARAVEL:
  121. case UNIT_GALLEON:
  122. unitPtr = new UnitMarine;
  123. break;
  124. case UNIT_EXPLOSIVE_CART:
  125. unitPtr = new UnitExpCart;
  126. break;
  127. default:
  128. if( unitInfo->is_monster )
  129. unitPtr = new UnitMonster;
  130. else if( unitInfo->solider_id ) // if it is a vehicle unit
  131. unitPtr = new UnitVehicle;
  132. else if( god_res.is_god_unit(unitId) )
  133. unitPtr = new UnitGod;
  134. else
  135. unitPtr = new Unit;
  136. }
  137. SpriteArray::add(unitPtr); // it set Sprite::sprite_recno
  138. return unitPtr;
  139. }
  140. //----------- End of function UnitArray::create_unit ---------//
  141. //-------- Begin of function UnitArray::unit_class_size --------//
  142. //
  143. // Return the size of the class.
  144. //
  145. int UnitArray::unit_class_size(int unitId)
  146. {
  147. UnitInfo* unitInfo = unit_res[unitId];
  148. switch(unitId)
  149. {
  150. case UNIT_CARAVAN:
  151. return sizeof(UnitCaravan);
  152. case UNIT_VESSEL:
  153. case UNIT_TRANSPORT:
  154. case UNIT_CARAVEL:
  155. case UNIT_GALLEON:
  156. return sizeof(UnitMarine);
  157. case UNIT_EXPLOSIVE_CART:
  158. return sizeof(UnitExpCart);
  159. default:
  160. if( unitInfo->is_monster )
  161. return sizeof(UnitMonster);
  162. else if( unitInfo->solider_id ) // if it is a vehicle unit
  163. return sizeof(UnitVehicle);
  164. else if( god_res.is_god_unit(unitId) )
  165. return sizeof(UnitGod);
  166. else
  167. return sizeof(Unit);
  168. }
  169. }
  170. //----------- End of function UnitArray::unit_class_size ---------//
  171. //-------- Begin of function UnitArray::disappear_in_town --------//
  172. //
  173. // The unit disappear from the map because it has moved into a town.
  174. //
  175. void UnitArray::disappear_in_town(int unitRecno, int townRecno)
  176. {
  177. Unit* unitPtr = unit_array[unitRecno];
  178. if( unitPtr->unit_mode == UNIT_MODE_REBEL )
  179. rebel_array.settle_town(unitRecno, townRecno);
  180. del(unitRecno); // delete it from unit_array
  181. }
  182. //----------- End of function UnitArray::disappear_in_town ---------//
  183. //-------- Begin of function UnitArray::disappear_in_firm --------//
  184. //
  185. // The unit disappear from the map because it has moved into a town.
  186. //
  187. void UnitArray::disappear_in_firm(int unitRecno)
  188. {
  189. Unit* unitPtr = unit_array[unitRecno];
  190. err_when( unitPtr->unit_mode == UNIT_MODE_REBEL ); // this shouldn't happen
  191. del(unitRecno); // delete it from unit_array
  192. }
  193. //----------- End of function UnitArray::disappear_in_firm ---------//
  194. //-------- Begin of function UnitArray::die --------//
  195. //
  196. void UnitArray::die(int unitRecno)
  197. {
  198. Unit* unitPtr = unit_array[unitRecno];
  199. if( unitPtr->unit_mode == UNIT_MODE_REBEL )
  200. rebel_array.drop_rebel_identity(unitRecno);
  201. unitPtr->die();
  202. del(unitRecno); // delete it from unit_array
  203. }
  204. //----------- End of function UnitArray::die ---------//
  205. //--------- Begin of function UnitArray::draw_dot ---------//
  206. //
  207. // Draw 2x2 tiny squares on map window representing the location of the unit ---//
  208. //
  209. void UnitArray::draw_dot()
  210. {
  211. char* vgaBufPtr = vga_back.buf_ptr();
  212. char* writePtr;
  213. int i, j, mapX, mapY;
  214. Unit* unitPtr;
  215. char* nationColorArray = nation_array.nation_color_array;
  216. char nationColor;
  217. int vgaBufPitch = vga_back.buf_pitch();
  218. const unsigned int excitedColorCount = 4;
  219. char excitedColorArray[MAX_NATION+1][excitedColorCount];
  220. short playerNationRecno = nation_array.player_recno;
  221. short lineFromX, lineFromY, lineToX, lineToY;
  222. int resultNodeRecno, resultNodeCount;
  223. ResultNode *resultNode1, *resultNode2;
  224. for( i = 0; i <= MAX_NATION; ++i )
  225. {
  226. if( i == 0 || !nation_array.is_deleted(i) )
  227. {
  228. char *remapTable = game.get_color_remap_table(i, 0);
  229. excitedColorArray[i][0] = remapTable[0xe0];
  230. excitedColorArray[i][1] = remapTable[0xe1];
  231. excitedColorArray[i][2] = remapTable[0xe2];
  232. excitedColorArray[i][3] = remapTable[0xe3];
  233. }
  234. else
  235. {
  236. excitedColorArray[i][0] =
  237. excitedColorArray[i][1] =
  238. excitedColorArray[i][2] =
  239. excitedColorArray[i][3] = (char) V_WHITE;
  240. }
  241. }
  242. int arraySize = size();
  243. int lineColor;
  244. //### begin alex 27/10 ###//
  245. //------------- set boundary of anim_line to mini-map ------------//
  246. short animLineBoundX1 = anim_line.bound_x1;
  247. short animLineBoundY1 = anim_line.bound_y1;
  248. short animLineBoundX2 = anim_line.bound_x2;
  249. short animLineBoundY2 = anim_line.bound_y2;
  250. anim_line.bound_x1 = MAP_X1;
  251. anim_line.bound_y1 = MAP_Y1;
  252. anim_line.bound_x2 = MAP_X2;
  253. anim_line.bound_y2 = MAP_Y2;
  254. //#### end alex 27/10 ####//
  255. for(i=1; i<=arraySize; i++)
  256. {
  257. unitPtr = (Unit*)get_ptr(i);
  258. if( !unitPtr || !unitPtr->is_visible() || unitPtr->is_shealth())
  259. continue;
  260. if( unitPtr->mobile_type == UNIT_SEA )
  261. lineColor = V_WHITE;
  262. else
  263. lineColor = V_BLACK;
  264. //---------------- draw unit path in mini_map ------------//
  265. if(unitPtr->selected_flag && (config.show_unit_path & 2) )
  266. {
  267. //#ifdef DEBUG
  268. //if(config.show_ai_info || unitPtr->nation_recno==playerNationRecno)
  269. //#else
  270. //if(unitPtr->nation_recno==playerNationRecno)
  271. //#endif
  272. if( config.show_ai_info || !playerNationRecno || unitPtr->is_nation(playerNationRecno) )
  273. {
  274. resultNodeRecno = unitPtr->result_node_recno;
  275. resultNodeCount = unitPtr->result_node_count;
  276. if(resultNodeCount && resultNodeRecno<=resultNodeCount)
  277. {
  278. //-----------------------------------------------------------//
  279. if(unitPtr->cur_x_loc()!=unitPtr->go_x_loc() || unitPtr->cur_y_loc()!=unitPtr->go_y_loc())
  280. {
  281. lineFromX = MAP_X1 + unitPtr->go_x_loc();
  282. lineFromY = MAP_Y1 + unitPtr->go_y_loc();
  283. lineToX = MAP_X1 + unitPtr->next_x_loc();
  284. lineToY = MAP_Y1 + unitPtr->next_y_loc();
  285. vga_back.line(lineFromX, lineFromY, lineToX, lineToY, lineColor);
  286. }
  287. //-----------------------------------------------------------//
  288. err_when(resultNodeRecno<1);
  289. resultNode1 = unitPtr->result_node_array + resultNodeRecno - 1;
  290. resultNode2 = resultNode1 + 1;
  291. for(j=resultNodeRecno+1; j<=resultNodeCount; j++, resultNode1++, resultNode2++)
  292. {
  293. lineFromX = MAP_X1 + resultNode2->node_x;
  294. lineFromY = MAP_Y1 + resultNode2->node_y;
  295. lineToX = MAP_X1 + resultNode1->node_x;
  296. lineToY = MAP_Y1 + resultNode1->node_y;
  297. vga_back.line(lineFromX, lineFromY, lineToX, lineToY, lineColor);
  298. }
  299. }
  300. //### begin alex 27/10 ###//
  301. //-------------- draw way_point on mini map ------------//
  302. if(unitPtr->way_point_count>1)
  303. {
  304. resultNode1 = unitPtr->way_point_array;
  305. resultNode2 = resultNode1+1;
  306. lineToX = MAP_X1 + resultNode1->node_x;
  307. lineToY = MAP_Y1 + resultNode1->node_y;
  308. for(j=unitPtr->way_point_count-1; j>0; j--, resultNode1++, resultNode2++)
  309. {
  310. lineFromX = MAP_X1 + resultNode2->node_x;
  311. lineFromY = MAP_Y1 + resultNode2->node_y;
  312. anim_line.draw_line(&vga_back, lineFromX, lineFromY, lineToX, lineToY, 0, 2);
  313. lineToX = lineFromX;
  314. lineToY = lineFromY;
  315. }
  316. }
  317. //#### end alex 27/10 ####//
  318. }
  319. }
  320. }
  321. //### begin alex 27/10 ###//
  322. //---------------- restore boundary setting of anim_line --------------//
  323. anim_line.bound_x1 = animLineBoundX1;
  324. anim_line.bound_y1 = animLineBoundY1;
  325. anim_line.bound_x2 = animLineBoundX2;
  326. anim_line.bound_y2 = animLineBoundY2;
  327. //#### end alex 27/10 ####//
  328. for(i=1; i<=arraySize; i++)
  329. {
  330. unitPtr = (Unit*)get_ptr(i);
  331. if( !unitPtr || !unitPtr->is_visible() || unitPtr->is_shealth())
  332. continue;
  333. mapX = MAP_X1 + unitPtr->cur_x_loc();
  334. mapY = MAP_Y1 + unitPtr->cur_y_loc();
  335. if( mapX == MAP_WIDTH-1 )
  336. mapX = MAP_WIDTH-2;
  337. if( mapY == MAP_HEIGHT-1 )
  338. mapY = MAP_HEIGHT-2;
  339. writePtr = vgaBufPtr + mapY*vgaBufPitch + mapX;
  340. nationColor = unitPtr->cur_action != SPRITE_ATTACK ?
  341. nationColorArray[unitPtr->nation_recno] :
  342. excitedColorArray[unitPtr->nation_recno][sys.frame_count % excitedColorCount];
  343. // ###### begin Gilbert 3/11 #######//
  344. int dotSize = unitPtr->mobile_type == UNIT_LAND ? 2 : 3;
  345. if( dotSize == 2 )
  346. {
  347. if( writePtr[0] != UNEXPLORED_COLOR )
  348. writePtr[0] = nationColor;
  349. if( writePtr[1] != UNEXPLORED_COLOR )
  350. writePtr[1] = nationColor;
  351. if( writePtr[vgaBufPitch] != UNEXPLORED_COLOR )
  352. writePtr[vgaBufPitch] = nationColor;
  353. if( writePtr[vgaBufPitch+1] != UNEXPLORED_COLOR )
  354. writePtr[vgaBufPitch+1] = nationColor;
  355. }
  356. else if( dotSize == 3 )
  357. {
  358. if( writePtr[-vgaBufPitch-1] != UNEXPLORED_COLOR )
  359. writePtr[-vgaBufPitch-1] = nationColor;
  360. if( writePtr[-vgaBufPitch] != UNEXPLORED_COLOR )
  361. writePtr[-vgaBufPitch] = nationColor;
  362. if( writePtr[-vgaBufPitch+1] != UNEXPLORED_COLOR )
  363. writePtr[-vgaBufPitch+1] = nationColor;
  364. if( writePtr[-1] != UNEXPLORED_COLOR )
  365. writePtr[-1] = nationColor;
  366. if( writePtr[0] != UNEXPLORED_COLOR )
  367. writePtr[0] = nationColor;
  368. if( writePtr[1] != UNEXPLORED_COLOR )
  369. writePtr[1] = nationColor;
  370. if( writePtr[vgaBufPitch-1] != UNEXPLORED_COLOR )
  371. writePtr[vgaBufPitch-1] = nationColor;
  372. if( writePtr[vgaBufPitch] != UNEXPLORED_COLOR )
  373. writePtr[vgaBufPitch] = nationColor;
  374. if( writePtr[vgaBufPitch+1] != UNEXPLORED_COLOR )
  375. writePtr[vgaBufPitch+1] = nationColor;
  376. }
  377. // ###### end Gilbert 3/11 #######//
  378. }
  379. }
  380. //----------- End of function UnitArray::draw_dot -----------//
  381. //--------- Begin of function UnitArray::draw_profile ---------//
  382. void UnitArray::draw_profile()
  383. {
  384. #ifdef DEBUG
  385. static unsigned long lastDrawTime = m.get_time();
  386. if(m.get_time() >= lastDrawTime + 1000)
  387. {
  388. //--------- update unit process profile ---------//
  389. last_unit_ai_profile_time = unit_ai_profile_time;
  390. unit_ai_profile_time = 0L;
  391. last_unit_profile_time = unit_profile_time;
  392. unit_profile_time = 0L;
  393. //--------- update seek path profile ---------//
  394. last_seek_path_profile_time = seek_path_profile_time;
  395. seek_path_profile_time = 0L;
  396. //--------- update sprite process profile --------//
  397. last_sprite_array_profile_time = sprite_array_profile_time;
  398. sprite_array_profile_time = 0L;
  399. //------- update sprite cur_action profile ---------//
  400. last_sprite_idle_profile_time = sprite_idle_profile_time;
  401. sprite_idle_profile_time = 0L;
  402. last_sprite_move_profile_time = sprite_move_profile_time;
  403. sprite_move_profile_time = 0L;
  404. last_sprite_wait_profile_time = sprite_wait_profile_time;
  405. sprite_wait_profile_time = 0L;
  406. last_sprite_attack_profile_time = sprite_attack_profile_time;
  407. sprite_attack_profile_time = 0L;
  408. last_unit_attack_profile_time = unit_attack_profile_time;
  409. unit_attack_profile_time = 0L;
  410. last_unit_assign_profile_time = unit_assign_profile_time;
  411. unit_assign_profile_time = 0L;
  412. lastDrawTime = m.get_time();
  413. }
  414. //------------ draw unit process profile -------------//
  415. int y=ZOOM_Y1+120;
  416. put_profile(y , "Unit AI:" , last_unit_ai_profile_time );
  417. put_profile(y+=20, "Unit:" , last_unit_profile_time );
  418. put_profile(y+=20, "Sprite:" , last_sprite_array_profile_time );
  419. put_profile(y+=20, "SeekPath:" , last_seek_path_profile_time );
  420. put_profile(y+=20, "Sprite Idle:" , last_sprite_idle_profile_time );
  421. put_profile(y+=20, "Sprite Move:" , last_sprite_move_profile_time );
  422. put_profile(y+=20, "Sprite Wait:" , last_sprite_wait_profile_time );
  423. put_profile(y+=20, "Sprite Attack:" , last_sprite_attack_profile_time );
  424. put_profile(y+=20, "Unit Attack:" , last_unit_attack_profile_time );
  425. put_profile(y+=20, "Unit Assign:" , last_unit_assign_profile_time );
  426. #endif
  427. }
  428. //----------- End of function UnitArray::draw_profile -----------//
  429. //--------- Begin of static function put_profile ---------//
  430. //
  431. static void put_profile(int y, char* dispDes, int dispValue)
  432. {
  433. font_news.put( ZOOM_X1+10, y, dispDes );
  434. font_news.put( ZOOM_X1+120, y, dispValue );
  435. }
  436. //----------- End of static function put_profile -----------//
  437. //--------- Begin of function UnitArray::process ---------//
  438. //
  439. // This function is called every frame.
  440. //
  441. void UnitArray::process()
  442. {
  443. #define SYS_YIELD_INTERVAL 50
  444. #define YEAR_FRAME_COUNT 365*FRAMES_PER_DAY // choose a value that is multiply of FRAMES_PER_DAY
  445. Unit* unitPtr;
  446. int i;
  447. int arraySize = size();
  448. int sysFrameCount = int(sys.frame_count%FRAMES_PER_DAY);
  449. int yearFrameCount = int(sys.frame_count%YEAR_FRAME_COUNT);
  450. int compareI = arraySize%FRAMES_PER_DAY;
  451. if(compareI < sysFrameCount)
  452. compareI += FRAMES_PER_DAY;
  453. int sysYieldCount = arraySize - arraySize%SYS_YIELD_INTERVAL;
  454. for(i=arraySize; i; --i, compareI--) // for(i=arraySize; i>0; --i, compareI++) or //for(i=1; i<=arraySize; i++, compareI++)
  455. {
  456. //-------- system yield ---------//
  457. if(i==sysYieldCount)
  458. {
  459. sysYieldCount -= SYS_YIELD_INTERVAL;
  460. sys.yield();
  461. }
  462. //-------------------------------//
  463. if(compareI == sysFrameCount)
  464. {
  465. compareI += FRAMES_PER_DAY;
  466. if( is_deleted(i) )
  467. continue;
  468. unitPtr = (Unit*) get_ptr(i);
  469. //-------------- reset ignore_power_nation ------------//
  470. if(compareI==yearFrameCount && unitPtr->unit_id!=UNIT_CARAVAN)
  471. unitPtr->ignore_power_nation = 0;
  472. unitPtr->next_day(); // although this function is called every frame, next_day() & process_ai() is only called once per day
  473. if( is_deleted(i) )
  474. continue;
  475. #ifdef DEBUG
  476. if(config.disable_ai_flag==0 && unitPtr->ai_unit)
  477. #else
  478. if( unitPtr->ai_unit )
  479. #endif
  480. {
  481. #ifdef DEBUG
  482. unsigned long profileAiStartTime = m.get_time();
  483. #endif
  484. unitPtr->process_ai();
  485. #ifdef DEBUG
  486. unit_ai_profile_time += m.get_time() - profileAiStartTime;
  487. #endif
  488. }
  489. //----- if it's an independent unit -------//
  490. else if( !unitPtr->nation_recno && unitPtr->race_id && !unitPtr->spy_recno)
  491. unitPtr->think_independent_unit();
  492. }
  493. }
  494. if(idle_blocked_unit_reset_count<50)
  495. idle_blocked_unit_reset_count++; // the ability to restart idle blocked attacking unit
  496. //------- process Sprite ---------//
  497. SpriteArray::process();
  498. }
  499. //----------- End of function UnitArray::process -----------//
  500. //--------- Begin of function UnitArray::update_selected_trade_unit_info ---------//
  501. // update trade information of trading units if these units are selected
  502. //
  503. void UnitArray::update_selected_trade_unit_info()
  504. {
  505. short playerNationRecno = nation_array.player_recno;
  506. Unit *unitPtr;
  507. UnitMarine *marinePtr;
  508. if(remote.is_enable())
  509. {
  510. for(int i=size(); i>0; --i)
  511. {
  512. if(is_deleted(i))
  513. continue;
  514. unitPtr = (Unit*)get_ptr(i);
  515. if(!unitPtr->is_visible())
  516. continue;
  517. switch(unitPtr->unit_id)
  518. {
  519. case UNIT_CARAVAN:
  520. if(mp_is_selected_caravan(i))
  521. ((UnitCaravan*) unitPtr)->update_stop_and_goods_info();
  522. break;
  523. case UNIT_VESSEL: case UNIT_CARAVEL: case UNIT_GALLEON:
  524. marinePtr = ((UnitMarine*) unitPtr);
  525. if(marinePtr->auto_mode && mp_is_selected_ship(i))
  526. marinePtr->update_stop_and_goods_info();
  527. break;
  528. default: break;
  529. }
  530. }
  531. }
  532. else if(selected_recno && !is_deleted(selected_recno))
  533. {
  534. unitPtr = (Unit*)get_ptr(selected_recno);
  535. if(unitPtr->nation_recno==playerNationRecno || config.show_ai_info)
  536. {
  537. switch(unitPtr->unit_id)
  538. {
  539. case UNIT_CARAVAN:
  540. ((UnitCaravan*) unitPtr)->update_stop_and_goods_info();
  541. break;
  542. case UNIT_VESSEL: case UNIT_CARAVEL: case UNIT_GALLEON:
  543. marinePtr = ((UnitMarine*) unitPtr);
  544. if(marinePtr->auto_mode)
  545. marinePtr->update_stop_and_goods_info();
  546. break;
  547. default:
  548. break;
  549. }
  550. }
  551. }
  552. }
  553. //----------- End of function UnitArray::update_selected_trade_unit_info -----------//
  554. //----------- Begin of function UnitArray::return_camp -----------//
  555. //
  556. // Order all units that are currently selected to return to their
  557. // home camp.
  558. //
  559. void UnitArray::return_camp(int remoteAction, short *selectedUnitArray, int selectedCount)
  560. {
  561. Unit* unitPtr;
  562. if( !selectedUnitArray )
  563. {
  564. if( !remoteAction && remote.is_enable() )
  565. {
  566. selectedCount = 0;
  567. int i;
  568. for( i=unit_array.size() ; i>0 ; i-- )
  569. {
  570. if( unit_array.is_deleted(i) )
  571. continue;
  572. unitPtr = this->operator[](i);
  573. if( !unitPtr->selected_flag || !unitPtr->is_visible() )
  574. continue;
  575. if(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE)
  576. continue;
  577. if( !unitPtr->is_own() ) // only if the unit belongs to us (a spy is also okay if true_nation_recno is ours)
  578. continue;
  579. //---------------------------------//
  580. if( unitPtr->home_camp_firm_recno )
  581. selectedCount++;
  582. }
  583. // packet structure : <no. of units> <unit recno>...
  584. short *shortPtr = (short *) remote.new_send_queue_msg(MSG_UNITS_RETURN_CAMP, (1+selectedCount)*sizeof(short) );
  585. *shortPtr = selectedCount;
  586. shortPtr++;
  587. int reCount = 0;
  588. for( i=unit_array.size() ; i>0 ; i-- )
  589. {
  590. if( unit_array.is_deleted(i) )
  591. continue;
  592. unitPtr = this->operator[](i);
  593. if( !unitPtr->selected_flag || !unitPtr->is_visible() )
  594. continue;
  595. if(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE)
  596. continue;
  597. if( !unitPtr->is_own() ) // only if the unit belongs to us (a spy is also okay if true_nation_recno is ours)
  598. continue;
  599. //---------------------------------//
  600. if( unitPtr->home_camp_firm_recno )
  601. {
  602. err_when( reCount > selectedCount );
  603. *shortPtr = i;
  604. shortPtr++;
  605. reCount++;
  606. }
  607. }
  608. err_when( reCount != selectedCount );
  609. return;
  610. }
  611. else
  612. {
  613. for( int i=unit_array.size() ; i>0 ; i-- )
  614. {
  615. if( unit_array.is_deleted(i) )
  616. continue;
  617. unitPtr = this->operator[](i);
  618. if( !unitPtr->selected_flag || !unitPtr->is_visible() )
  619. continue;
  620. if(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE)
  621. continue;
  622. if( !unitPtr->is_own() ) // only if the unit belongs to us (a spy is also okay if true_nation_recno is ours)
  623. continue;
  624. //---------------------------------//
  625. if( unitPtr->home_camp_firm_recno )
  626. unitPtr->return_camp();
  627. }
  628. }
  629. }
  630. else
  631. {
  632. if( !remoteAction && remote.is_enable() )
  633. {
  634. if( selectedCount > 0)
  635. {
  636. // packet structure : <no. of units> <unit recno>...
  637. short *shortPtr = (short *) remote.new_send_queue_msg(MSG_UNITS_RETURN_CAMP, (1+selectedCount)*sizeof(short) );
  638. *shortPtr = selectedCount;
  639. shortPtr++;
  640. memcpy(shortPtr, selectedUnitArray, sizeof(short)*selectedCount );
  641. }
  642. return;
  643. }
  644. else
  645. {
  646. for( int j = selectedCount-1; j >= 0; j--)
  647. {
  648. // descending unit recno
  649. int i = selectedUnitArray[j];
  650. if( unit_array.is_deleted(i) )
  651. continue;
  652. unitPtr = this->operator[](i);
  653. if( !unitPtr->is_visible() )
  654. continue;
  655. if(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE)
  656. continue;
  657. //---------------------------------//
  658. if( unitPtr->home_camp_firm_recno )
  659. unitPtr->return_camp();
  660. }
  661. }
  662. }
  663. }
  664. //----------- End of function UnitArray::return_camp -----------//
  665. #ifdef DEBUG
  666. //------- Begin of function UnitArray::operator[] -----//
  667. Unit* UnitArray::operator[](int recNo)
  668. {
  669. Unit* unitPtr = (Unit*) get_ptr(recNo);
  670. if( !unitPtr )
  671. err.run( "UnitArray[] is deleted" );
  672. return unitPtr;
  673. }
  674. //--------- End of function UnitArray::operator[] ----//
  675. #endif
  676. //------- Begin of function UnitArray::is_deleted -----//
  677. int UnitArray::is_deleted(int recNo)
  678. {
  679. Unit *unitPtr = (Unit*) get_ptr(recNo);
  680. if( !unitPtr )
  681. return 1;
  682. if( unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode==ACTION_DIE )
  683. return 1;
  684. return 0;
  685. }
  686. //--------- End of function UnitArray::is_deleted ----//
  687. //------- Begin of function UnitArray::is_truly_deleted -----//
  688. int UnitArray::is_truly_deleted(int recNo)
  689. {
  690. return get_ptr(recNo) == NULL;
  691. }
  692. //--------- End of function UnitArray::is_truly_deleted ----//