OU_MARI.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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 : OU_MARI.CPP
  21. // Description : sea unit
  22. #include <OSYS.h>
  23. #include <OTERRAIN.h>
  24. #include <OU_CARA.h>
  25. #include <OPOWER.h>
  26. #include <OU_MARI.h>
  27. #include <OREMOTE.h>
  28. #include <ONATIONA.h>
  29. #include <OCONFIG.h>
  30. #ifdef DEBUG2
  31. #include <OFONT.h>
  32. #endif
  33. //------- Define constant ----------//
  34. const int WAVE_CYCLE = 8;
  35. //------- Begin of function UnitMarine::UnitMarine -------//
  36. UnitMarine::UnitMarine()
  37. {
  38. menu_mode = 0;
  39. extra_move_in_beach = NO_EXTRA_MOVE;
  40. in_beach = 0;
  41. selected_unit_id = 0;
  42. //------- transporting units vars ---------//
  43. unit_count = 0;
  44. memset(unit_recno_array, 0, sizeof(short)*MAX_UNIT_IN_SHIP);
  45. //------- transporting goods vars ---------//
  46. memset( stop_array, 0, MAX_STOP_FOR_SHIP * sizeof(ShipStop) );
  47. journey_status = ON_WAY_TO_FIRM;
  48. dest_stop_id = 0;
  49. stop_defined_num = 0;
  50. wait_count = 0;
  51. stop_x_loc = 0;
  52. stop_y_loc = 0;
  53. memset(raw_qty_array, 0, sizeof(short)*MAX_RAW);
  54. memset(product_raw_qty_array, 0, sizeof(short)*MAX_PRODUCT);
  55. auto_mode = 1; // there should be no button to toggle it if the ship is only for trading
  56. cur_firm_recno = 0;
  57. }
  58. //------- End of function UnitMarine::UnitMarine -------//
  59. //------- Begin of function UnitMarine::~UnitMarine -------//
  60. UnitMarine::~UnitMarine()
  61. {
  62. //-------- del those units in the ship -------//
  63. for(int i=0; i<unit_count; i++)
  64. {
  65. if( !unit_array.SpriteArray::is_deleted(unit_recno_array[i]) )
  66. unit_array.del(unit_recno_array[i]);
  67. }
  68. }
  69. //------- End of function UnitMarine::~UnitMarine -------//
  70. //------- Begin of function UnitMarine::init -------//
  71. void UnitMarine::init(int unitId, int nationRecno, int rankId, int unitLoyalty, int startX, int startY)
  72. {
  73. attack_mode_selected = 0; // for fix_attack_info() to set attack_info_array
  74. Unit::init(unitId, nationRecno, rankId, unitLoyalty, startX, startY);
  75. short spriteId = sprite_info->get_sub_sprite_info(1)->sprite_id;
  76. splash.init( spriteId, cur_x_loc(), cur_y_loc() );
  77. splash.cur_frame = 1;
  78. //------- set carry_goods_capacity -------//
  79. carry_goods_capacity = unit_res[unitId]->carry_goods_capacity;
  80. //------- set menu mode of the unit -------//
  81. UnitInfo* unitInfo = unit_res[unitId];
  82. if( unitInfo->carry_unit_capacity==0 && unitInfo->carry_goods_capacity>0 ) // if this ship only carries goods
  83. menu_mode = SHIP_MENU_GOODS;
  84. else
  85. menu_mode = SHIP_MENU_UNIT;
  86. }
  87. //------- End of function UnitMarine::init -------//
  88. //------- Begin of function UnitMarine::update_abs_pos ------//
  89. void UnitMarine::update_abs_pos(SpriteFrame *spriteFrame)
  90. {
  91. Unit::update_abs_pos(spriteFrame);
  92. short h = wave_height(6);
  93. abs_y1 -= h;
  94. abs_y2 -= h;
  95. }
  96. //------- End of function UnitMarine::update_abs_pos -------//
  97. //------- Begin of function UnitMarine::draw -------//
  98. void UnitMarine::draw()
  99. {
  100. // -------- update splash parameter --------//
  101. // ###### begin Gilbert 8/9 #######//
  102. char oldSplashAction = splash.cur_action;
  103. switch(cur_action)
  104. {
  105. case SPRITE_MOVE:
  106. splash.cur_action = SPRITE_MOVE;
  107. if( splash.cur_action != oldSplashAction)
  108. splash.cur_frame = 1;
  109. else
  110. {
  111. ++splash.cur_frame;
  112. if( splash.cur_frame < 1 || splash.cur_frame > splash.cur_sprite_move()->frame_count )
  113. splash.cur_frame = 1;
  114. }
  115. break;
  116. default:
  117. splash.cur_action = SPRITE_IDLE;
  118. if( splash.cur_action != oldSplashAction)
  119. splash.cur_frame = 1;
  120. else
  121. {
  122. ++splash.cur_frame;
  123. if( splash.cur_frame < 1 || splash.cur_frame > splash.cur_sprite_stop()->frame_count)
  124. splash.cur_frame = 1;
  125. }
  126. break;
  127. }
  128. // ###### end Gilbert 8/9 #######//
  129. splash.cur_x = cur_x;
  130. splash.cur_y = cur_y - wave_height(7);
  131. splash.cur_dir = cur_dir;
  132. splash.final_dir = final_dir;
  133. splash.turn_delay = turn_delay;
  134. // --------- draw splash and then the unit --------//
  135. // ###### begin Gilbert 24/9 #######//
  136. if( cur_action != SPRITE_DIE )
  137. splash.draw();
  138. // ###### end Gilbert 24/9 #######//
  139. Unit::draw();
  140. #ifdef DEBUG2
  141. if(selected_flag && 0)
  142. {
  143. vga.d3_panel_up( INFO_X1, INFO_Y1+144, INFO_X2, INFO_Y1+144+87 );
  144. int x=INFO_X1+4, y=INFO_Y1+200, refreshFlag=INFO_REPAINT;
  145. font_san.field( x, y, " " , x+2, sprite_recno, 1, INFO_X2-2, refreshFlag);
  146. font_san.field( x+20, y, " " , x+22, next_x_loc(), 1, INFO_X2-2, refreshFlag);
  147. font_san.field( x+50, y, " " , x+52, next_y_loc(), 1, INFO_X2-2, refreshFlag);
  148. font_san.field( x+70, y, " " , x+72, nation_recno, 1, INFO_X2-2, refreshFlag);
  149. font_san.field( x+100, y, " " , x+102, action_mode, 1, INFO_X2-2, refreshFlag);
  150. font_san.field( x+120, y, " " , x+122, action_para, 1, INFO_X2-2, refreshFlag);
  151. font_san.field( x+140, y, " " , x+142, action_x_loc, 1, INFO_X2-2, refreshFlag);
  152. font_san.field( x+160, y, " " , x+162, action_y_loc, 1, INFO_X2-2, refreshFlag);
  153. y-=20;
  154. font_san.field( x+100, y, " " , x+102, action_mode2, 1, INFO_X2-2, refreshFlag);
  155. font_san.field( x+120, y, " " , x+122, action_para2, 1, INFO_X2-2, refreshFlag);
  156. font_san.field( x+140, y, " " , x+142, action_x_loc2, 1, INFO_X2-2, refreshFlag);
  157. font_san.field( x+160, y, " " , x+162, action_y_loc2, 1, INFO_X2-2, refreshFlag);
  158. y-=20;
  159. font_san.field( x+160, y, " " , x+162, cur_action, 1, INFO_X2-2, refreshFlag);
  160. }
  161. #endif
  162. }
  163. //------- End of function UnitMarine::draw -------//
  164. //------- Begin of function UnitMarine::draw_outlined -------//
  165. void UnitMarine::draw_outlined()
  166. {
  167. // -------- update splash parameter --------//
  168. // ###### begin Gilbert 8/9 #######//
  169. char oldSplashAction = splash.cur_action;
  170. switch(cur_action)
  171. {
  172. case SPRITE_MOVE:
  173. splash.cur_action = SPRITE_MOVE;
  174. if( splash.cur_action != oldSplashAction)
  175. splash.cur_frame = 1;
  176. else
  177. {
  178. ++splash.cur_frame;
  179. if( splash.cur_frame < 1 || splash.cur_frame > splash.cur_sprite_move()->frame_count )
  180. splash.cur_frame = 1;
  181. }
  182. break;
  183. default:
  184. splash.cur_action = SPRITE_IDLE;
  185. if( splash.cur_action != oldSplashAction)
  186. splash.cur_frame = 1;
  187. else
  188. {
  189. ++splash.cur_frame;
  190. if( splash.cur_frame < 1 || splash.cur_frame > splash.cur_sprite_stop()->frame_count)
  191. splash.cur_frame = 1;
  192. }
  193. break;
  194. }
  195. // ###### end Gilbert 8/9 #######//
  196. splash.cur_x = cur_x;
  197. splash.cur_y = cur_y - wave_height(7);
  198. splash.cur_dir = cur_dir;
  199. splash.final_dir = final_dir;
  200. splash.turn_delay = turn_delay;
  201. // --------- draw splash and then the unit --------//
  202. // ###### begin Gilbert 24/9 #######//
  203. if( cur_action != SPRITE_DIE )
  204. splash.draw();
  205. // ###### end Gilbert 24/9 #######//
  206. Unit::draw_outlined();
  207. #ifdef DEBUG2
  208. if(selected_flag && 0)
  209. {
  210. vga.d3_panel_up( INFO_X1, INFO_Y1+144, INFO_X2, INFO_Y1+144+87 );
  211. int x=INFO_X1+4, y=INFO_Y1+200, refreshFlag=INFO_REPAINT;
  212. font_san.field( x, y, " " , x+2, sprite_recno, 1, INFO_X2-2, refreshFlag);
  213. font_san.field( x+20, y, " " , x+22, next_x_loc(), 1, INFO_X2-2, refreshFlag);
  214. font_san.field( x+50, y, " " , x+52, next_y_loc(), 1, INFO_X2-2, refreshFlag);
  215. font_san.field( x+70, y, " " , x+72, nation_recno, 1, INFO_X2-2, refreshFlag);
  216. font_san.field( x+100, y, " " , x+102, action_mode, 1, INFO_X2-2, refreshFlag);
  217. font_san.field( x+120, y, " " , x+122, action_para, 1, INFO_X2-2, refreshFlag);
  218. font_san.field( x+140, y, " " , x+142, action_x_loc, 1, INFO_X2-2, refreshFlag);
  219. font_san.field( x+160, y, " " , x+162, action_y_loc, 1, INFO_X2-2, refreshFlag);
  220. y-=20;
  221. font_san.field( x+100, y, " " , x+102, action_mode2, 1, INFO_X2-2, refreshFlag);
  222. font_san.field( x+120, y, " " , x+122, action_para2, 1, INFO_X2-2, refreshFlag);
  223. font_san.field( x+140, y, " " , x+142, action_x_loc2, 1, INFO_X2-2, refreshFlag);
  224. font_san.field( x+160, y, " " , x+162, action_y_loc2, 1, INFO_X2-2, refreshFlag);
  225. y-=20;
  226. font_san.field( x+160, y, " " , x+162, cur_action, 1, INFO_X2-2, refreshFlag);
  227. }
  228. #endif
  229. }
  230. //------- End of function UnitMarine::draw_outlined -------//
  231. //------- Begin of function UnitMarine::wave_height -------//
  232. short UnitMarine::wave_height(int phase)
  233. {
  234. err_when( phase < 0);
  235. static short height[WAVE_CYCLE] = { 4,3,2,1,0,1,2,3 };
  236. return height[((sys.frame_count /4) + phase) % WAVE_CYCLE];
  237. }
  238. //------- End of function UnitMarine::wave_height -------//
  239. //--------- Begin of function UnitMarine::del_unit ---------//
  240. //
  241. // Delete a unit from the ship. This function is called by
  242. // Unit::deinit() when the unit is killed.
  243. //
  244. // <int> unitRecno - recno of the unit to be loaded.
  245. //
  246. void UnitMarine::del_unit(int unitRecno)
  247. {
  248. for( int i=0 ; i<unit_count ; i++ )
  249. {
  250. if( unit_recno_array[i] == unitRecno )
  251. {
  252. err_when( unit_count > MAX_UNIT_IN_SHIP );
  253. m.del_array_rec(unit_recno_array, unit_count, sizeof(unit_recno_array[0]), i+1);
  254. return;
  255. }
  256. }
  257. err_here();
  258. }
  259. //----------- End of function UnitMarine::del_unit -----------//
  260. //--------- Begin of function UnitMarine::load_unit ---------//
  261. //
  262. // Load an unit to the ship.
  263. //
  264. // <int> unitRecno - recno of the unit to be loaded.
  265. //
  266. void UnitMarine::load_unit(int unitRecno)
  267. {
  268. if(unit_array.is_deleted(unitRecno))
  269. return;
  270. Unit *unitPtr = unit_array[unitRecno];
  271. if(unitPtr->hit_points<=0 || unitPtr->cur_action==SPRITE_DIE || unitPtr->action_mode2==ACTION_DIE)
  272. return;
  273. if( unit_count == MAX_UNIT_IN_SHIP )
  274. return;
  275. unit_recno_array[unit_count++] = unitRecno;
  276. unitPtr->set_mode(UNIT_MODE_ON_SHIP, sprite_recno); // set unit mode
  277. if(unitPtr->selected_flag)
  278. {
  279. unitPtr->selected_flag = 0;
  280. unit_array.selected_count--;
  281. }
  282. unitPtr->deinit_sprite();
  283. //--- if this marine unit is currently selected ---//
  284. if(unit_array.selected_recno==sprite_recno)
  285. {
  286. if(!remote.is_enable() || nation_recno==nation_array.player_recno || config.show_ai_info)
  287. disp_info(INFO_UPDATE);
  288. }
  289. }
  290. //----------- End of function UnitMarine::load_unit -----------//
  291. //--------- Begin of function UnitMarine::unload_unit ---------//
  292. //
  293. // Unload an unit from the ship.
  294. //
  295. // <int> unitSeqId - sequence id. of the unit in unit_recno_array[]
  296. //
  297. void UnitMarine::unload_unit(int unitSeqId, char remoteAction)
  298. {
  299. err_when(unitSeqId > unit_count);
  300. if(!remoteAction && remote.is_enable() )
  301. {
  302. // packet structure : <unit recno> <unitSeqId>
  303. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_U_SHIP_UNLOAD_UNIT, 2*sizeof(short));
  304. *shortPtr = sprite_recno;
  305. shortPtr[1] = unitSeqId;
  306. return;
  307. }
  308. //-------- unload unit now -------//
  309. if( unloading_unit(0, unitSeqId-1) ) // unit is unloaded
  310. {
  311. err_when( unit_count+1 > MAX_UNIT_IN_SHIP );
  312. m.del_array_rec(unit_recno_array, unit_count+1, sizeof(unit_recno_array[0]), unitSeqId);
  313. }
  314. }
  315. //----------- End of function UnitMarine::unload_unit -----------//
  316. //--------- Begin of function UnitMarine::unload_all_units ---------//
  317. void UnitMarine::unload_all_units(char remoteAction)
  318. {
  319. if(!remoteAction && remote.is_enable() )
  320. {
  321. // packet structure : <unit recno>
  322. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_U_SHIP_UNLOAD_ALL_UNITS, sizeof(short));
  323. *shortPtr = sprite_recno;
  324. return;
  325. }
  326. unloading_unit(1); // unload all units
  327. }
  328. //----------- End of function UnitMarine::unload_all_units -----------//
  329. //--------- Begin of function UnitMarine::unloading_unit ---------//
  330. //
  331. // <int> isAll - 1 for unload all the units
  332. // - otherwise 0
  333. // <int> unitSeqId - if(isAll==0) unitSeqId+1 is the recno of the
  334. // selected unit in unit_recno_array[]
  335. //
  336. int UnitMarine::unloading_unit(int isAll, int unitSeqId)
  337. {
  338. if( !is_on_coast() )
  339. return 0;
  340. //-------------------------------------------------------------------------//
  341. // return if no territory is nearby the ship
  342. //-------------------------------------------------------------------------//
  343. int curXLoc = next_x_loc(); // ship location
  344. int curYLoc = next_y_loc();
  345. int unprocess = isAll ? unit_count : 1;
  346. Unit *unitPtr = isAll ? unit_array[unit_recno_array[unprocess-1]] : unit_array[unit_recno_array[unitSeqId]];
  347. Location *locPtr;
  348. int xShift, yShift, checkXLoc, checkYLoc;
  349. int regionId = 0; // unload all the units in the same territory
  350. int found, i = 2;
  351. int sqtSize = 3, sqtArea = sqtSize*sqtSize;
  352. #ifdef DEBUG
  353. long debugCount = 0L;
  354. #endif
  355. if(isAll && nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button.
  356. power.reset_selection();
  357. while(unprocess) // using the calculated 'i' to reduce useless calculation
  358. {
  359. err_when(debugCount++ > 4*long(MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC));
  360. m.cal_move_around_a_point(i, MAX_WORLD_X_LOC, MAX_WORLD_Y_LOC, xShift, yShift);
  361. checkXLoc = curXLoc+xShift;
  362. checkYLoc = curYLoc+yShift;
  363. if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
  364. {
  365. i++;
  366. continue;
  367. }
  368. locPtr = world.get_loc(checkXLoc, checkYLoc);
  369. //-------------------------------------------------------------------------//
  370. // check for space to unload the unit
  371. //-------------------------------------------------------------------------//
  372. if(!regionId || locPtr->region_id == regionId)
  373. {
  374. if(locPtr->walkable())
  375. found = 1;
  376. if(locPtr->can_move(UNIT_LAND))//unitPtr->mobile_type))
  377. {
  378. regionId = locPtr->region_id;
  379. unitPtr->init_sprite(checkXLoc, checkYLoc);
  380. unitPtr->set_mode(0);
  381. if( isAll && nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button.
  382. {
  383. unitPtr->selected_flag = 1; // mark selected if unload all
  384. unit_array.selected_count++;
  385. if( !unit_array.selected_recno )
  386. unit_array.selected_recno = unitPtr->sprite_recno;
  387. }
  388. unprocess--;
  389. unit_count--;
  390. if(unprocess)
  391. unitPtr = unit_array[unit_recno_array[unprocess-1]]; // point to next unit
  392. else
  393. break; // finished, all have been unloaded
  394. }
  395. }
  396. //-------------------------------------------------------------------------//
  397. // stop checking if there is totally bouned by unacessible location
  398. //-------------------------------------------------------------------------//
  399. if(i==sqtArea)
  400. {
  401. if(found)
  402. {
  403. found = 0; // reset found
  404. sqtSize += 2;
  405. sqtArea = sqtSize*sqtSize;
  406. }
  407. else // no continuous location for the unit to unload, some units can't be unloaded
  408. return 0;
  409. }
  410. i++;
  411. }
  412. //-------- display info --------//
  413. if( nation_recno == nation_array.player_recno ) // for player's camp, patrol() can only be called when the player presses the button.
  414. info.disp();
  415. return 1;
  416. }
  417. //----------- End of function UnitMarine::unloading_unit -----------//
  418. //--------- Begin of function UnitMarine::is_on_coast ---------//
  419. //
  420. // Return whether the unit is on the coast and ready for unloading.
  421. //
  422. int UnitMarine::is_on_coast()
  423. {
  424. Location *locPtr;
  425. int xShift, yShift, checkXLoc, checkYLoc, found=0;
  426. int curXLoc = next_x_loc(); // ship location
  427. int curYLoc = next_y_loc();
  428. for(int i=2; i<=9; i++) // checking for the surrouding location
  429. {
  430. m.cal_move_around_a_point(i, 3, 3, xShift, yShift);
  431. checkXLoc = curXLoc + xShift;
  432. checkYLoc = curYLoc + yShift;
  433. if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
  434. continue;
  435. locPtr = world.get_loc(checkXLoc, checkYLoc);
  436. if(terrain_res[locPtr->terrain_id]->average_type!=TERRAIN_OCEAN && // a territory nearby
  437. locPtr->walkable())
  438. {
  439. return 1;
  440. }
  441. }
  442. return 0;
  443. }
  444. //----------- End of function UnitMarine::is_on_coast -----------//
  445. //--------- Begin of function UnitMarine::extra_move ---------//
  446. void UnitMarine::extra_move()
  447. {
  448. static char offset[3] = {0, 1, -1};
  449. int curXLoc = next_x_loc();
  450. int curYLoc = next_y_loc();
  451. int vecX = action_x_loc2 - curXLoc;
  452. int vecY = action_y_loc2 - curYLoc;
  453. int checkXLoc, checkYLoc, i, found=0;
  454. if(vecX==0 || vecY==0)
  455. {
  456. if(vecX==0)
  457. {
  458. vecY /= abs(vecY);
  459. checkYLoc = curYLoc + vecY;
  460. }
  461. else // vecY==0
  462. {
  463. vecX /= abs(vecX);
  464. checkXLoc = curXLoc + vecX;
  465. }
  466. for(i=0; i<3; i++)
  467. {
  468. if(vecX==0)
  469. checkXLoc = curXLoc + offset[i];
  470. else
  471. checkYLoc = curYLoc + offset[i];
  472. if(checkXLoc<0 || checkXLoc>=MAX_WORLD_X_LOC || checkYLoc<0 || checkYLoc>=MAX_WORLD_Y_LOC)
  473. continue;
  474. if(world.get_loc(checkXLoc, checkYLoc)->can_move(mobile_type))
  475. {
  476. found++;
  477. break;
  478. }
  479. }
  480. }
  481. else
  482. {
  483. vecX /= abs(vecX);
  484. vecY /= abs(vecY);
  485. checkXLoc = curXLoc + vecX;
  486. checkYLoc = curYLoc + vecY;
  487. if(world.get_loc(checkXLoc, checkYLoc)->can_move(mobile_type))
  488. found++;
  489. }
  490. if(!found)
  491. return;
  492. set_dir(curXLoc, curYLoc, checkXLoc, checkYLoc);
  493. cur_action = SPRITE_SHIP_EXTRA_MOVE;
  494. go_x = checkXLoc*ZOOM_LOC_WIDTH;
  495. go_y = checkYLoc*ZOOM_LOC_HEIGHT;
  496. err_when(cur_x==go_x && cur_y==go_y);
  497. //extra_move_in_beach = EXTRA_MOVING_IN;
  498. }
  499. //----------- End of function UnitMarine::extra_move -----------//
  500. //------- Begin of function UnitMarine::process_extra_move ------//
  501. void UnitMarine::process_extra_move()
  502. {
  503. static short vector_x_array[] = { 0, 1, 1, 1, 0, -1, -1, -1}; // default vectors, temporary only
  504. static short vector_y_array[] = {-1, -1, 0, 1, 1, 1, 0, -1};
  505. if(!match_dir()) // process turning
  506. return;
  507. if(cur_x!=go_x || cur_y!=go_y)
  508. {
  509. //------------------------------------------------------------------------//
  510. // set cargo_recno, extra_move_in_beach
  511. //------------------------------------------------------------------------//
  512. if(cur_x==next_x && cur_y==next_y)
  513. {
  514. int goXLoc = go_x>>ZOOM_X_SHIFT_COUNT;
  515. int goYLoc = go_y>>ZOOM_Y_SHIFT_COUNT;
  516. if(!world.get_loc(goXLoc, goYLoc)->can_move(mobile_type))
  517. {
  518. go_x = next_x;
  519. go_y = next_y;
  520. return;
  521. }
  522. int curXLoc = next_x_loc();
  523. int curYLoc = next_y_loc();
  524. world.set_unit_recno(curXLoc, curYLoc, mobile_type, 0);
  525. world.set_unit_recno(goXLoc, goYLoc, mobile_type, sprite_recno);
  526. next_x = go_x;
  527. next_y = go_y;
  528. err_when( ((curXLoc%2)|(curYLoc%2)) + ((goXLoc%2)|(goYLoc%2)) != 1); // one pair location must be even, another is not even
  529. in_beach = !(curXLoc%2 || curYLoc%2);
  530. if(goXLoc%2 || goYLoc%2) // not even location
  531. extra_move_in_beach = EXTRA_MOVING_IN;
  532. else // even location
  533. extra_move_in_beach = EXTRA_MOVING_OUT;
  534. }
  535. //else
  536. // int debug = 0;
  537. //---------- process moving -----------//
  538. short stepX = sprite_info->speed;
  539. short stepY = sprite_info->speed;
  540. short vectorX = vector_x_array[final_dir] * sprite_info->speed; // cur_dir may be changed in the above set_next() call
  541. short vectorY = vector_y_array[final_dir] * sprite_info->speed;
  542. if(abs(cur_x-go_x) <= stepX)
  543. cur_x = go_x;
  544. else
  545. cur_x += vectorX;
  546. if(abs(cur_y-go_y) <= stepY)
  547. cur_y = go_y;
  548. else
  549. cur_y += vectorY;
  550. err_when(extra_move_in_beach!=EXTRA_MOVING_IN && extra_move_in_beach!=EXTRA_MOVING_OUT);
  551. err_when(cur_action!=SPRITE_SHIP_EXTRA_MOVE);
  552. }
  553. if(cur_x==go_x && cur_y==go_y)
  554. {
  555. if(result_node_array==NULL)
  556. {
  557. cur_action = SPRITE_IDLE;
  558. cur_frame = 1;
  559. move_to_x_loc = next_x_loc();
  560. move_to_y_loc = next_y_loc();
  561. }
  562. else
  563. {
  564. cur_action = SPRITE_MOVE;
  565. next_move();
  566. }
  567. if(in_beach)
  568. {
  569. extra_move_in_beach = EXTRA_MOVE_FINISH;
  570. err_when(move_to_x_loc%2==0 && move_to_y_loc%2==0);
  571. err_when(result_node_array || result_path_dist);
  572. }
  573. else
  574. {
  575. extra_move_in_beach = NO_EXTRA_MOVE;
  576. err_when(move_to_x_loc%2 || move_to_y_loc%2);
  577. err_when(result_node_array || result_path_dist);
  578. }
  579. err_when(cur_action==SPRITE_IDLE && (extra_move_in_beach==EXTRA_MOVING_IN || extra_move_in_beach==EXTRA_MOVING_OUT));
  580. }
  581. }
  582. //----------- End of function UnitMarine::process_extra_move -----------//
  583. //------------ Begin of function UnitMarine::actual_damage --------------//
  584. //
  585. // This function returns the actual hit damage this unit can do to a target.
  586. //
  587. float UnitMarine::actual_damage()
  588. {
  589. float attackDamage = Unit::actual_damage();
  590. //-----------------------------------------//
  591. //
  592. // If there is units on the ship, the units
  593. // leadership will increase the attacking damage.
  594. //
  595. // actual damage = normal damage X (100+highest leadership unit on the ship) / 100
  596. //
  597. //-----------------------------------------//
  598. Unit* unitPtr;
  599. int t, highestLeadership=0;
  600. for( int i=0 ; i<unit_count ; i++ )
  601. {
  602. unitPtr = unit_array[ unit_recno_array[i] ];
  603. if( unitPtr->skill.skill_id == SKILL_LEADING )
  604. {
  605. if( (t=unitPtr->skill.skill_level) > highestLeadership )
  606. highestLeadership = t;
  607. }
  608. }
  609. return attackDamage * (100+highestLeadership) / 100;
  610. }
  611. //------------ End of function UnitMarine::actual_damage --------------//
  612. //------- Begin of function UnitMarine::total_carried_goods -------//
  613. int UnitMarine::total_carried_goods()
  614. {
  615. int totalQty=0;
  616. for( int i=0 ; i<MAX_RAW ; i++ )
  617. {
  618. totalQty += raw_qty_array[i];
  619. totalQty += product_raw_qty_array[i];
  620. }
  621. return totalQty;
  622. }
  623. //------- End of function UnitMarine::total_carried_goods -------//
  624. //------- Begin of function UnitMarine::can_resign -------//
  625. int UnitMarine::can_resign()
  626. {
  627. err_when(unit_count < 0);
  628. return unit_count == 0;
  629. }
  630. //------- End of function UnitMarine::can_resign -------//