OUNITAC.cpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
  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 : OUNITM.CPP
  21. //Description : Object Unit misc. actions excluding attacking and moving functions
  22. //Owner : Alex
  23. #include <ALL.h>
  24. #include <OWORLD.h>
  25. #include <OFIRM.h>
  26. #include <ONATION.h>
  27. #include <ORACERES.h>
  28. #include <OTOWN.h>
  29. #include <OU_MARI.h>
  30. #include <OF_CAMP.h>
  31. #include <OREMOTE.h>
  32. #include <OF_MONS.h>
  33. #include <OU_GOD.h>
  34. #include <OF_HARB.h>
  35. #ifdef NO_DEBUG_UNIT
  36. #undef err_when
  37. #undef err_here
  38. #undef err_if
  39. #undef err_else
  40. #undef err_now
  41. #define err_when(cond)
  42. #define err_here()
  43. #define err_if(cond)
  44. #define err_else
  45. #define err_now(msg)
  46. #undef DEBUG
  47. #endif
  48. //--------- Begin of function Unit::build_firm ---------//
  49. // Build a firm.
  50. //
  51. // <int> buildXLoc, buildYLoc - the location to build
  52. // <int> firmId - id. of the firm to build
  53. //
  54. // [char] remoteAction
  55. //
  56. void Unit::build_firm(int buildXLoc, int buildYLoc, int firmId, char remoteAction)
  57. {
  58. err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
  59. if(!remoteAction && remote.is_enable() )
  60. {
  61. // packet structure : <unit recno> <xLoc> <yLoc> <firmId>
  62. short *shortPtr =(short *)remote.new_send_queue_msg(MSG_UNIT_BUILD_FIRM, 4*sizeof(short) );
  63. shortPtr[0] = sprite_recno;
  64. shortPtr[1] = buildXLoc;
  65. shortPtr[2] = buildYLoc;
  66. shortPtr[3] = firmId;
  67. return;
  68. }
  69. //----------------------------------------------------------------//
  70. // return if the unit is dead
  71. //----------------------------------------------------------------//
  72. if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
  73. return;
  74. //----------------------------------------------------------------//
  75. // location is blocked, cannot build. so move there instead
  76. //----------------------------------------------------------------//
  77. if(!world.can_build_firm(buildXLoc, buildYLoc, firmId, sprite_recno))
  78. {
  79. //reset_action_para2();
  80. move_to(buildXLoc, buildYLoc);
  81. return;
  82. }
  83. //----------------------------------------------------------------//
  84. // different territory
  85. //----------------------------------------------------------------//
  86. int harborDir = world.can_build_firm(buildXLoc, buildYLoc, firmId, sprite_recno);
  87. int goX = buildXLoc, goY = buildYLoc;
  88. if( firm_res[firmId]->tera_type == 4)
  89. {
  90. switch(harborDir)
  91. {
  92. case 1: // north exit
  93. goX += 1;
  94. goY += 2;
  95. break;
  96. case 2: // south exit
  97. goX += 1;
  98. break;
  99. case 4: // west exit
  100. goX += 2;
  101. goY += 1;
  102. break;
  103. case 8: // east exit
  104. goY += 1;
  105. break;
  106. default:
  107. err_here();
  108. move_to(buildXLoc, buildYLoc);
  109. return;
  110. }
  111. if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(goX,goY)->region_id)
  112. {
  113. move_to(buildXLoc, buildYLoc);
  114. return;
  115. }
  116. }
  117. else
  118. {
  119. if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(buildXLoc, buildYLoc)->region_id)
  120. {
  121. move_to(buildXLoc, buildYLoc);
  122. return;
  123. }
  124. }
  125. //----------------------------------------------------------------//
  126. // action_mode2: checking for equal action or idle action
  127. //----------------------------------------------------------------//
  128. if(action_mode2==ACTION_BUILD_FIRM && action_para2==firmId && action_x_loc2==buildXLoc && action_y_loc2==buildYLoc)
  129. {
  130. if(cur_action!=SPRITE_IDLE)
  131. return;
  132. }
  133. else
  134. {
  135. //----------------------------------------------------------------//
  136. // action_mode2: store new order
  137. //----------------------------------------------------------------//
  138. action_mode2 = ACTION_BUILD_FIRM;
  139. action_para2 = firmId;
  140. action_x_loc2 = buildXLoc;
  141. action_y_loc2 = buildYLoc;
  142. }
  143. //----- order the sprite to stop as soon as possible -----//
  144. stop(); // new order
  145. //---------------- define parameters -------------------//
  146. FirmInfo* firmInfo = firm_res[firmId];
  147. int firmWidth = firmInfo->loc_width;
  148. int firmHeight = firmInfo->loc_height;
  149. if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, buildXLoc, buildYLoc, firmWidth, firmHeight))
  150. {
  151. //----------- not in the firm surrounding ---------//
  152. set_move_to_surround(buildXLoc, buildYLoc, firmWidth, firmHeight, BUILDING_TYPE_FIRM_BUILD, firmId);
  153. }
  154. else
  155. {
  156. //------- the unit is in the firm surrounding -------//
  157. set_cur(next_x, next_y);
  158. set_dir(move_to_x_loc, move_to_y_loc, buildXLoc+firmWidth/2, buildYLoc+firmHeight/2);
  159. }
  160. //----------- set action to build the firm -----------//
  161. action_mode = ACTION_BUILD_FIRM;
  162. action_para = firmId;
  163. action_x_loc = buildXLoc;
  164. action_y_loc = buildYLoc;
  165. }
  166. //----------- End of function Unit::build_firm -----------//
  167. //--------- Begin of function Unit::burn ---------//
  168. //
  169. // Burn a locaiton
  170. //
  171. // <int> burnXLoc, burnYLoc - the location to burn
  172. //
  173. void Unit::burn(int burnXLoc, int burnYLoc, char remoteAction)
  174. {
  175. err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
  176. if( !remoteAction && remote.is_enable() )
  177. {
  178. // packet structure : <unit recno> <xLoc> <yLoc>
  179. short *shortPtr = (short *)remote.new_send_queue_msg(MSG_UNIT_BURN, 3*sizeof(short) );
  180. shortPtr[0] = sprite_recno;
  181. shortPtr[1] = burnXLoc;
  182. shortPtr[2] = burnYLoc;
  183. return;
  184. }
  185. if(move_to_x_loc==burnXLoc && move_to_y_loc==burnYLoc)
  186. return; // should not burn the unit itself
  187. //----------------------------------------------------------------//
  188. // return if the unit is dead
  189. //----------------------------------------------------------------//
  190. if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
  191. return;
  192. //----------------------------------------------------------------//
  193. // move there instead if ordering to different territory
  194. //----------------------------------------------------------------//
  195. if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(burnXLoc, burnYLoc)->region_id)
  196. {
  197. move_to(burnXLoc, burnYLoc);
  198. return;
  199. }
  200. //----------------------------------------------------------------//
  201. // action_mode2: checking for equal action or idle action
  202. //----------------------------------------------------------------//
  203. if(action_mode2==ACTION_BURN && action_x_loc2==burnXLoc && action_y_loc2==burnYLoc)
  204. {
  205. if(cur_action!=SPRITE_IDLE)
  206. return;
  207. }
  208. else
  209. {
  210. //----------------------------------------------------------------//
  211. // action_mode2: store new order
  212. //----------------------------------------------------------------//
  213. action_mode2 = ACTION_BURN;
  214. action_para2 = 0;
  215. action_x_loc2 = burnXLoc;
  216. action_y_loc2 = burnYLoc;
  217. }
  218. //----- order the sprite to stop as soon as possible -----//
  219. stop(); // new order
  220. if(abs(burnXLoc-next_x_loc())>1 || abs(burnYLoc-next_y_loc())>1)
  221. {
  222. //--- if the unit is not in the burning surrounding location, move there first ---//
  223. search(burnXLoc, burnYLoc, 1, SEARCH_MODE_A_UNIT_IN_GROUP);
  224. if(move_to_x_loc != burnXLoc || move_to_y_loc != burnYLoc) // cannot reach the destination
  225. {
  226. action_mode = ACTION_BURN;
  227. action_para = 0;
  228. action_x_loc = burnXLoc;
  229. action_y_loc = burnYLoc;
  230. return; // just move to the closest location returned by shortest path searching
  231. }
  232. }
  233. else
  234. {
  235. if(cur_x==next_x && cur_y==next_y)
  236. set_dir(next_x_loc(), next_y_loc(), burnXLoc, burnYLoc);
  237. err_when((cur_x!=next_x || cur_y!=next_y) && (check_unit_dir1=get_dir(cur_x,cur_y,next_x,next_y))!=final_dir);
  238. err_when(result_node_array || result_node_count || result_path_dist);
  239. }
  240. //--------------------------------------------------------//
  241. // edit the result path such that the unit can reach the
  242. // burning location surrounding
  243. //--------------------------------------------------------//
  244. if(result_node_array && result_node_count)
  245. {
  246. //--------------------------------------------------------//
  247. // there should be at least two nodes, and should take at
  248. // least two steps to the destination
  249. //--------------------------------------------------------//
  250. err_when(move_to_x_loc!=burnXLoc || move_to_y_loc!=burnYLoc);
  251. err_when(result_node_count<2);
  252. ResultNode* lastNode1 = result_node_array+result_node_count-1; // the last node
  253. ResultNode* lastNode2 = result_node_array+result_node_count-2; // the node before the last node
  254. int vX = lastNode1->node_x-lastNode2->node_x; // get the vectors direction
  255. int vY = lastNode1->node_y-lastNode2->node_y;
  256. int vDirX = (vX) ? vX/abs(vX) : 0;
  257. int vDirY = (vY) ? vY/abs(vY) : 0;
  258. if(result_node_count>2) // go_? should not be the burning location
  259. {
  260. err_when(go_x>>ZOOM_X_SHIFT_COUNT==burnXLoc && go_y>>ZOOM_Y_SHIFT_COUNT==burnYLoc);
  261. err_when(vX!=0 && vY!=0 && abs(vX)!=abs(vY));
  262. if(abs(vX)>1 || abs(vY)>1)
  263. {
  264. lastNode1->node_x -= vDirX;
  265. lastNode1->node_y -= vDirY;
  266. move_to_x_loc = lastNode1->node_x;
  267. move_to_y_loc = lastNode1->node_y;
  268. }
  269. else // move only one step
  270. {
  271. result_node_count--; // remove a node
  272. move_to_x_loc = lastNode2->node_x;
  273. move_to_y_loc = lastNode2->node_y;
  274. }
  275. }
  276. else // go_? may be the burning location
  277. {
  278. err_when(result_node_count!=2);
  279. lastNode1->node_x -= vDirX;
  280. lastNode1->node_y -= vDirY;
  281. if(go_x>>ZOOM_X_SHIFT_COUNT==burnXLoc && go_y>>ZOOM_Y_SHIFT_COUNT==burnYLoc) // go_? is the burning location
  282. {
  283. //--- edit parameters such that only moving to the nearby location to do the action ---//
  284. err_when(abs(vX)<=1 && abs(vY)<=1); // this case should be handled before
  285. go_x = lastNode1->node_x * ZOOM_LOC_WIDTH;
  286. go_y = lastNode1->node_y * ZOOM_LOC_HEIGHT;
  287. }
  288. //else the unit is still doing sthg else, no action here
  289. move_to_x_loc = lastNode1->node_x;
  290. move_to_y_loc = lastNode1->node_y;
  291. }
  292. //--------------------------------------------------------------//
  293. // reduce the result_path_dist by 1
  294. //--------------------------------------------------------------//
  295. result_path_dist--;
  296. #ifdef DEBUG
  297. ResultNode *preNode = result_node_array;
  298. ResultNode *curNode = result_node_array+1;
  299. int debugCount=1;
  300. int debugDist = 0;
  301. int xDist = abs(next_x_loc()-preNode->node_x);
  302. int yDist = abs(next_y_loc()-preNode->node_y);
  303. debugDist -= (xDist) ? xDist : yDist;
  304. while(debugCount++ < result_node_count)
  305. {
  306. err_when(debugCount>1000);
  307. xDist = abs(preNode->node_x - curNode->node_x);
  308. yDist = abs(preNode->node_y - curNode->node_y);
  309. debugDist += (xDist) ? xDist : yDist;
  310. preNode++;
  311. curNode++;
  312. }
  313. err_when(result_path_dist!=debugDist);
  314. #endif
  315. err_when((cur_x!=next_x || cur_y!=next_y) && // is not blocked
  316. (check_unit_dir1=get_dir(cur_x, cur_y, next_x, next_y))!=(check_unit_dir2=get_dir(cur_x, cur_y, go_x, go_y)));
  317. }
  318. err_when(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, burnXLoc, burnYLoc, 1, 1));
  319. //-- set action if the burning location can be reached, otherwise just move nearby --//
  320. action_mode = ACTION_BURN;
  321. action_para = 0;
  322. action_x_loc = burnXLoc;
  323. action_y_loc = burnYLoc;
  324. }
  325. //----------- End of function Unit::burn -----------//
  326. //--------- Begin of function Unit::settle ---------//
  327. //
  328. // settle to a town
  329. //
  330. // <int> settleXLoc, settleYLoc - the location to settle
  331. // [short] curSettleUnitNum - the number to call this function by
  332. // a group of unit. (default: 1)
  333. //
  334. void Unit::settle(int settleXLoc, int settleYLoc, short curSettleUnitNum)
  335. {
  336. err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
  337. //----------------------------------------------------------------//
  338. // return if the unit is dead
  339. //----------------------------------------------------------------//
  340. if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
  341. return;
  342. //---------- no settle for non-human -----------//
  343. if(unit_res[unit_id]->unit_class!=UNIT_CLASS_HUMAN)
  344. return;
  345. //----------------------------------------------------------------//
  346. // move there if cannot settle
  347. //----------------------------------------------------------------//
  348. if(!world.can_build_town(settleXLoc, settleYLoc, sprite_recno))
  349. {
  350. Location *locPtr = world.get_loc(settleXLoc, settleYLoc);
  351. if(locPtr->is_town() && town_array[locPtr->town_recno()]->nation_recno==nation_recno)
  352. assign(settleXLoc, settleYLoc);
  353. else
  354. move_to(settleXLoc, settleYLoc);
  355. return;
  356. }
  357. //----------------------------------------------------------------//
  358. // move there if location is in different territory
  359. //----------------------------------------------------------------//
  360. if(world.get_loc(next_x_loc(), next_y_loc())->region_id!=world.get_loc(settleXLoc, settleYLoc)->region_id)
  361. {
  362. move_to(settleXLoc, settleYLoc);
  363. return;
  364. }
  365. //----------------------------------------------------------------//
  366. // action_mode2: checking for equal action or idle action
  367. //----------------------------------------------------------------//
  368. if(action_mode2==ACTION_SETTLE && action_x_loc2==settleXLoc && action_y_loc2==settleYLoc)
  369. {
  370. if(cur_action!=SPRITE_IDLE)
  371. return;
  372. }
  373. else
  374. {
  375. //----------------------------------------------------------------//
  376. // action_mode2: store new order
  377. //----------------------------------------------------------------//
  378. action_mode2 = ACTION_SETTLE;
  379. action_para2 = 0;
  380. action_x_loc2 = settleXLoc;
  381. action_y_loc2 = settleYLoc;
  382. }
  383. //----- order the sprite to stop as soon as possible -----//
  384. stop(); // new order
  385. if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, settleXLoc, settleYLoc,
  386. STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
  387. {
  388. //------------ not in the town surrounding ------------//
  389. set_move_to_surround(settleXLoc, settleYLoc, STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT, BUILDING_TYPE_SETTLE, 0, 0, curSettleUnitNum);
  390. }
  391. else
  392. {
  393. //------- the unit is within the settle location -------//
  394. set_cur(next_x, next_y);
  395. set_dir(move_to_x_loc, move_to_y_loc, settleXLoc+STD_TOWN_LOC_WIDTH/2, settleYLoc+STD_TOWN_LOC_HEIGHT/2);
  396. }
  397. //----------- set action to settle -----------//
  398. action_mode = ACTION_SETTLE;
  399. action_para = 0;
  400. action_x_loc = settleXLoc;
  401. action_y_loc = settleYLoc;
  402. }
  403. //----------- End of function Unit::settle -----------//
  404. //--------- Begin of function Unit::assign ---------//
  405. //
  406. // Assign an unit to :
  407. //
  408. // - a firm as an overseer, as a worker
  409. // - a town as a citizen
  410. // - a vehicle
  411. //
  412. // <int> buildXLoc, buildYLoc - the location to build
  413. //
  414. void Unit::assign(int assignXLoc, int assignYLoc, short curAssignUnitNum)
  415. {
  416. err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
  417. //----------------------------------------------------------------//
  418. // return if the unit is dead
  419. //----------------------------------------------------------------//
  420. if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
  421. return;
  422. //----------- cannot assign for caravan -----------//
  423. if(unit_id==UNIT_CARAVAN)
  424. return;
  425. //----------------------------------------------------------------//
  426. // move there if the destination in other territory
  427. //----------------------------------------------------------------//
  428. Location *locPtr = world.get_loc(assignXLoc, assignYLoc);
  429. UCHAR unitRegionId = world.get_loc(next_x_loc(), next_y_loc())->region_id;
  430. if(locPtr->is_firm())
  431. {
  432. Firm *firmPtr = firm_array[locPtr->firm_recno()];
  433. int quit = 0;
  434. if(firmPtr->firm_id==FIRM_HARBOR)
  435. {
  436. FirmHarbor *harborPtr = (FirmHarbor*) firmPtr;
  437. switch(unit_res[unit_id]->unit_class)
  438. {
  439. case UNIT_CLASS_HUMAN:
  440. if(unitRegionId != harborPtr->land_region_id)
  441. quit = 1;
  442. break;
  443. case UNIT_CLASS_SHIP:
  444. if(unitRegionId != harborPtr->sea_region_id)
  445. quit = 1;
  446. break;
  447. default: err_here();
  448. break;
  449. }
  450. }
  451. else if(unitRegionId!=locPtr->region_id)
  452. quit = 1;
  453. if(quit)
  454. {
  455. move_to_firm_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id);
  456. return;
  457. }
  458. }
  459. else if(unitRegionId!=locPtr->region_id)
  460. {
  461. if(locPtr->is_town())
  462. move_to_town_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height);
  463. /*else if(locPtr->has_unit(UNIT_LAND))
  464. {
  465. Unit *unitPtr = unit_array[locPtr->unit_recno(UNIT_LAND)];
  466. move_to_unit_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height, unitPtr->sprite_recno);
  467. }*/
  468. return;
  469. }
  470. //---------------- define parameters --------------------//
  471. int width, height;
  472. int buildingType=0; // 1 for Firm, 2 for TownZone
  473. short recno;
  474. int firmNeedUnit=1;
  475. if(locPtr->is_firm())
  476. {
  477. //-------------------------------------------------------//
  478. // the location is firm
  479. //-------------------------------------------------------//
  480. recno = locPtr->firm_recno();
  481. //----------------------------------------------------------------//
  482. // action_mode2: checking for equal action or idle action
  483. //----------------------------------------------------------------//
  484. if(action_mode2==ACTION_ASSIGN_TO_FIRM && action_para2==recno && action_x_loc2==assignXLoc && action_y_loc2==assignYLoc)
  485. {
  486. if(cur_action!=SPRITE_IDLE)
  487. return;
  488. }
  489. else
  490. {
  491. //----------------------------------------------------------------//
  492. // action_mode2: store new order
  493. //----------------------------------------------------------------//
  494. action_mode2 = ACTION_ASSIGN_TO_FIRM;
  495. action_para2 = recno;
  496. action_x_loc2 = assignXLoc;
  497. action_y_loc2 = assignYLoc;
  498. }
  499. Firm *firmPtr = firm_array[recno];
  500. FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
  501. if(!firm_can_assign(recno))
  502. {
  503. //firmNeedUnit = 0; // move to the surrounding of the firm
  504. move_to_firm_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height, firmPtr->firm_id);
  505. return;
  506. }
  507. width = firmInfo->loc_width;
  508. height = firmInfo->loc_height;
  509. buildingType = BUILDING_TYPE_FIRM_MOVE_TO;
  510. }
  511. else if(locPtr->is_town()) // there is town
  512. {
  513. if(unit_res[unit_id]->unit_class != UNIT_CLASS_HUMAN)
  514. return;
  515. //-------------------------------------------------------//
  516. // the location is town
  517. //-------------------------------------------------------//
  518. recno = locPtr->town_recno();
  519. //----------------------------------------------------------------//
  520. // action_mode2: checking for equal action or idle action
  521. //----------------------------------------------------------------//
  522. if(action_mode2==ACTION_ASSIGN_TO_TOWN && action_para2==recno && action_x_loc2==assignXLoc && action_y_loc2==assignYLoc)
  523. {
  524. if(cur_action!=SPRITE_IDLE)
  525. return;
  526. }
  527. else
  528. {
  529. //----------------------------------------------------------------//
  530. // action_mode2: store new order
  531. //----------------------------------------------------------------//
  532. action_mode2 = ACTION_ASSIGN_TO_TOWN;
  533. action_para2 = recno;
  534. action_x_loc2 = assignXLoc;
  535. action_y_loc2 = assignYLoc;
  536. }
  537. Town *targetTown = town_array[recno];
  538. if(town_array[recno]->nation_recno != nation_recno)
  539. {
  540. move_to_town_surround(assignXLoc, assignYLoc, sprite_info->loc_width, sprite_info->loc_height);
  541. return;
  542. }
  543. width = targetTown->loc_width();
  544. height = targetTown->loc_height();
  545. buildingType = BUILDING_TYPE_TOWN_MOVE_TO;
  546. }
  547. /*else if(locPtr->has_unit(UNIT_LAND)) // there is vehicle
  548. {
  549. //-------------------------------------------------------//
  550. // the location is vehicle
  551. //-------------------------------------------------------//
  552. Unit* vehicleUnit = unit_array[locPtr->unit_recno(UNIT_LAND)];
  553. if( vehicleUnit->unit_id!=unit_res[unit_id]->vehicle_id )
  554. return;
  555. recno = vehicleUnit->sprite_recno;
  556. //----------------------------------------------------------------//
  557. // action_mode2: checking for equal action or idle action
  558. //----------------------------------------------------------------//
  559. if(action_mode2==ACTION_ASSIGN_TO_VEHICLE && action_para2==recno && action_x_loc2==assignXLoc && action_y_loc2==assignYLoc)
  560. {
  561. if(cur_action!=SPRITE_IDLE)
  562. return;
  563. }
  564. else
  565. {
  566. //----------------------------------------------------------------//
  567. // action_mode2: store new order
  568. //----------------------------------------------------------------//
  569. action_mode2 = ACTION_ASSIGN_TO_VEHICLE;
  570. action_para2 = recno;
  571. action_x_loc2 = assignXLoc;
  572. action_y_loc2 = assignYLoc;
  573. }
  574. SpriteInfo* spriteInfo = vehicleUnit->sprite_info;
  575. width = spriteInfo->loc_width;
  576. height = spriteInfo->loc_height;
  577. buildingType = BUILDING_TYPE_VEHICLE;
  578. }*/
  579. else
  580. {
  581. stop2(KEEP_DEFENSE_MODE);
  582. return;
  583. }
  584. //-----------------------------------------------------------------//
  585. // order the sprite to stop as soon as possible (new order)
  586. //-----------------------------------------------------------------//
  587. stop();
  588. set_move_to_surround(assignXLoc, assignYLoc, width, height, buildingType, 0, 0, curAssignUnitNum);
  589. //-----------------------------------------------------------------//
  590. // able to reach building surrounding, set action parameters
  591. //-----------------------------------------------------------------//
  592. action_para = recno;
  593. action_x_loc = assignXLoc;
  594. action_y_loc = assignYLoc;
  595. switch(buildingType)
  596. {
  597. case BUILDING_TYPE_FIRM_MOVE_TO:
  598. action_mode = ACTION_ASSIGN_TO_FIRM;
  599. break;
  600. case BUILDING_TYPE_TOWN_MOVE_TO:
  601. action_mode = ACTION_ASSIGN_TO_TOWN;
  602. break;
  603. case BUILDING_TYPE_VEHICLE:
  604. action_mode = ACTION_ASSIGN_TO_VEHICLE;
  605. break;
  606. }
  607. //##### begin trevor 9/10 #######//
  608. // force_move_flag = 1; // don't stop and fight back on an assign mission
  609. //##### end trevor 9/10 #######//
  610. //-----------------------------------------------------------------//
  611. // edit parameters for those firms don't need unit
  612. //-----------------------------------------------------------------//
  613. /*if(!firmNeedUnit)
  614. {
  615. action_mode2 = action_mode = ACTION_MOVE;
  616. action_para2 = action_para = 0;
  617. action_x_loc2 = action_x_loc = move_to_x_loc;
  618. action_y_loc2 = action_y_loc = move_to_y_loc;
  619. }*/
  620. }
  621. //----------- End of function Unit::assign -----------//
  622. //--------- Begin of function Unit::firm_can_assign ---------//
  623. // return 1 for true, i.e. unit can assign to the firm
  624. // return 2 for assigning leader
  625. // return 3 for repair
  626. // return 4 for spy assigning to inn
  627. // return 5 for capture (not used)
  628. // return 0 otherwise
  629. //
  630. int Unit::firm_can_assign(short firmRecno)
  631. {
  632. Firm *firmPtr = firm_array[firmRecno];
  633. FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
  634. switch( unit_res[unit_id]->unit_class )
  635. {
  636. case UNIT_CLASS_HUMAN:
  637. if( nation_recno == firmPtr->nation_recno )
  638. {
  639. if( skill.skill_id == SKILL_CONSTRUCTION && firmPtr->firm_id != FIRM_MONSTER)
  640. {
  641. return 3;
  642. }
  643. // ###### begin Gilbert 22/10 #######//
  644. //----------------------------------------//
  645. // If this is a spy, then he can only be
  646. // assigned to an enemy firm when there is
  647. // space for the unit.
  648. //----------------------------------------//
  649. //if( spy_recno && true_nation_recno() != firmPtr->nation_recno )
  650. //{
  651. // if( rank_id == RANK_GENERAL )
  652. // {
  653. // if( firmPtr->overseer_recno )
  654. // return 0;
  655. // }
  656. // else
  657. // {
  658. // if( firmPtr->worker_count == MAX_WORKER )
  659. // return 0;
  660. // }
  661. //}
  662. //--------------------------------------//
  663. // ###### end Gilbert 22/10 #######//
  664. switch( firmPtr->firm_id )
  665. {
  666. case FIRM_CAMP:
  667. return rank_id == RANK_SOLDIER ? 1 : 2;
  668. case FIRM_BASE:
  669. if(race_id == firmPtr->race_id)
  670. {
  671. if( !skill.skill_id || skill.skill_id==SKILL_PRAYING) // non-skilled worker
  672. return 1;
  673. if( rank_id != RANK_SOLDIER )
  674. return 2;
  675. }
  676. break;
  677. //case FIRM_INN:
  678. // shealthed soldier spy can assign to inn
  679. // return rank_id == RANK_SOLDIER && nation_recno != true_nation_recno() ? 4 : 0;
  680. default:
  681. return rank_id == RANK_SOLDIER && firmInfo->need_unit() ? 1 : 0;
  682. }
  683. }
  684. break;
  685. case UNIT_CLASS_WEAPON:
  686. if(firmPtr->firm_id == FIRM_CAMP && nation_recno == firmPtr->nation_recno)
  687. return 1;
  688. break;
  689. case UNIT_CLASS_SHIP:
  690. if(firmPtr->firm_id == FIRM_HARBOR && nation_recno == firmPtr->nation_recno)
  691. return 1;
  692. break;
  693. case UNIT_CLASS_MONSTER:
  694. if(firmPtr->firm_id == FIRM_MONSTER && mobile_type == UNIT_LAND)
  695. {
  696. // BUGHERE : suppose only land monster can assign
  697. return rank_id == RANK_SOLDIER ? 1 : 2;
  698. }
  699. break;
  700. case UNIT_CLASS_GOD:
  701. case UNIT_CLASS_CARAVAN:
  702. break;
  703. default:
  704. err_here(); // undefined unit class
  705. }
  706. return 0;
  707. }
  708. //----------- End of function Unit::firm_can_assign -----------//
  709. //--------- Begin of function Unit::set_move_to_surround ---------//
  710. // Mode 1:
  711. // return 1 if the unit can reach the surrounding of the firm
  712. // return 0 otherwise.
  713. //
  714. // Mode 2:
  715. // In this mode, the unit calling this function is ordered to move to
  716. // location a little bit away from the surrounding of the object.
  717. //
  718. // return 1 if the unit can move to there
  719. // return 0 otherwise
  720. //
  721. // <int> buildXLoc - upper left x location of the building (firm/town)
  722. // <int> buildYLoc - upper left y location of the building
  723. // <int> width - width of the building
  724. // <int> height - height of the building
  725. // <int> buildingType - used to determine how searching is processed
  726. // [int] miscNo - firm_id of firm if buildingType==BUILDING_TYPE_FIRM_BUILD
  727. // - 0 for group search (for wall, firm)
  728. // - 1 for a unit search
  729. // [short] readyDist - the extra distance the unit stands from the building
  730. // (default 0, i.e. the surrounding of the building)
  731. // [short] curProcessUnitNum - the cur unit no. in a group calling this function
  732. // (default 1)
  733. //
  734. //============================================================================//
  735. // Note: This funcion should not change any action parameters
  736. //============================================================================//
  737. //
  738. int Unit::set_move_to_surround(int buildXLoc, int buildYLoc, int width, int height, int buildingType, int miscNo, int readyDist, short curProcessUnitNum)
  739. {
  740. err_when(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE);
  741. //--------------------------------------------------------------//
  742. // calculate the distance from the object
  743. //--------------------------------------------------------------//
  744. int found=0, foundAgain=0;
  745. int distance = cal_distance(buildXLoc, buildYLoc, width, height); // 0 for inside, 1 for surrounding, >1 for the rest
  746. //--------------------------------------------------------------//
  747. // inside the building
  748. //--------------------------------------------------------------//
  749. if(!distance)
  750. {
  751. reset_path();
  752. if(cur_x==next_x && cur_y==next_y)
  753. set_idle();
  754. return 1;
  755. }
  756. if(distance>1)
  757. {
  758. //--------------------------------------------------------------//
  759. // the searching is divided into 2 parts.
  760. //
  761. // part 1 using the firm_type and firm_id to find a shortest path.
  762. //
  763. // part 2
  764. // if the width and height is the actual width and height of the
  765. // firm, the unit move to the surrounding of the firm.
  766. //
  767. // if the width and height > the actual width and height of the
  768. // firm, the unit move to a location far away from the surrounding
  769. // of the firm.
  770. //--------------------------------------------------------------//
  771. //====================================================================//
  772. // part 1
  773. //====================================================================//
  774. Location *locPtr = world.get_loc( buildXLoc, buildYLoc );
  775. Firm *firmPtr = NULL;
  776. Town *targetTown = NULL;
  777. int searchResult;
  778. switch(buildingType)
  779. {
  780. case BUILDING_TYPE_FIRM_MOVE_TO: // (assign) firm is on the location
  781. firmPtr = firm_array[locPtr->firm_recno()];
  782. searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_FIRM, firmPtr->firm_id, curProcessUnitNum);
  783. break;
  784. case BUILDING_TYPE_FIRM_BUILD: // (build firm) no firm on the location
  785. err_when(sprite_info->loc_width>1);
  786. searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_FIRM, miscNo);
  787. break;
  788. case BUILDING_TYPE_TOWN_MOVE_TO: // (assign) town is on the location
  789. targetTown = town_array[locPtr->town_recno()];
  790. searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_TOWN, targetTown->town_recno, curProcessUnitNum);
  791. break;
  792. case BUILDING_TYPE_SETTLE: // (settle, first unit) no town on the location
  793. //---------------------------------------------------------------------//
  794. // the record number sent to the searching algorithm is used to determine
  795. // the width and the height of the building. However, the standard
  796. // dimension for settling is used and the building built is a type of
  797. // town. Thus, passing -1 as the recno. to show that "settle" is
  798. // processed
  799. //---------------------------------------------------------------------//
  800. err_when(sprite_info->loc_width>1);
  801. searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_TOWN, -1, curProcessUnitNum);
  802. break;
  803. case BUILDING_TYPE_VEHICLE:
  804. err_when(sprite_info->loc_width>1);
  805. searchResult = search(buildXLoc, buildYLoc, 1, SEARCH_MODE_TO_VEHICLE, (short)world.get_loc(buildXLoc, buildYLoc)->cargo_recno);
  806. break;
  807. case BUILDING_TYPE_WALL: // wall is on the location
  808. err_when(miscNo!=0 && miscNo!=1);
  809. searchResult = search(buildXLoc, buildYLoc, 1, miscNo?SEARCH_MODE_TO_WALL_FOR_UNIT:SEARCH_MODE_TO_WALL_FOR_GROUP);
  810. break;
  811. default: err_here();
  812. break;
  813. }
  814. if(!searchResult)
  815. return 0; // incomplete searching
  816. //====================================================================//
  817. // part 2
  818. //====================================================================//
  819. if(result_node_array && result_node_count)
  820. return edit_path_to_surround(buildXLoc, buildYLoc, buildXLoc+width-1, buildYLoc+height-1, readyDist);
  821. else
  822. return 0;
  823. }
  824. else // in the surrounding, no need to move
  825. {
  826. reset_path();
  827. err_when(distance!=1);
  828. if(cur_x==next_x && cur_y==next_y)
  829. {
  830. move_to_x_loc = next_x_loc();
  831. move_to_y_loc = next_y_loc();
  832. go_x = cur_x;
  833. go_y = cur_y;
  834. set_idle();
  835. set_dir(move_to_x_loc, move_to_y_loc, buildXLoc + width/2, buildYLoc + height/2);
  836. err_when(result_node_array!=NULL);
  837. }
  838. err_when(cur_action==SPRITE_IDLE && (move_to_x_loc!=next_x_loc() || move_to_y_loc!=next_y_loc()));
  839. err_when(cur_action==SPRITE_IDLE && (cur_x!=next_x || cur_y!=next_y));
  840. return 1;
  841. }
  842. }
  843. //----------- End of function Unit::set_move_to_surround -----------//
  844. //--------- Begin of function Unit::edit_path_to_surround ---------//
  845. // edit the path such that the unit only move to the surrounding of the firm
  846. //
  847. // <int> objectXLoc1, objectYLoc1 - object top_left position
  848. // <int> objectXLoc2, objectYLoc2 - object bottom_right position
  849. // <short> readyDist - the extra distance the unit stands from the building
  850. // (default 0, i.e. the surrounding of the building)
  851. //
  852. // return 1 if able to reach object surrounding
  853. // return 0 otherwise
  854. //
  855. int Unit::edit_path_to_surround(int objectXLoc1, int objectYLoc1, int objectXLoc2, int objectYLoc2, int readyDist)
  856. {
  857. err_when(!result_node_array || !result_node_count);
  858. if(result_node_count<2)
  859. return 0;
  860. //----------------------------------------------------------------------------//
  861. // At this moment, the unit generally has a path to the location inside the object,
  862. // walk through it and extract a path to the surrounding of the object.
  863. //----------------------------------------------------------------------------//
  864. //------- calculate the surrounding top-left and bottom-right points ------//
  865. int moveScale = move_step_magn();
  866. int xLoc1 = objectXLoc1 - readyDist - 1;
  867. int yLoc1 = objectYLoc1 - readyDist - 1;
  868. int xLoc2 = objectXLoc2 + readyDist + 1;
  869. int yLoc2 = objectYLoc2 + readyDist + 1;
  870. //------------------- boundary checking -------------------//
  871. if(xLoc1<0) xLoc1 = 0;
  872. if(yLoc1<0) yLoc1 = 0;
  873. if(xLoc2>=MAX_WORLD_X_LOC) yLoc1 = MAX_WORLD_X_LOC - moveScale;
  874. if(yLoc2>=MAX_WORLD_Y_LOC) xLoc2 = MAX_WORLD_Y_LOC - moveScale;
  875. //--------------- adjust for air and sea units -----------------//
  876. if(mobile_type!=UNIT_LAND)
  877. {
  878. //------ assume even x, y coordinate is used for UNIT_SEA and UNIT_AIR -------//
  879. if(xLoc1%2) xLoc1--;
  880. if(yLoc1%2) yLoc1--;
  881. if(xLoc2%2) xLoc2++;
  882. if(yLoc2%2) yLoc2++;
  883. if(xLoc2>MAX_WORLD_X_LOC-moveScale)
  884. xLoc2 = MAX_WORLD_X_LOC-moveScale;
  885. if(yLoc2>MAX_WORLD_Y_LOC-moveScale)
  886. yLoc2 = MAX_WORLD_Y_LOC-moveScale;
  887. err_when(xLoc1<0 || yLoc1<0);
  888. err_when(xLoc2>MAX_WORLD_X_LOC-moveScale || yLoc2>MAX_WORLD_Y_LOC-moveScale);
  889. }
  890. int checkXLoc = next_x_loc();
  891. int checkYLoc = next_y_loc();
  892. ResultNode *editNode1 = result_node_array; // alias the unit's result_node_array
  893. ResultNode *editNode2 = result_node_array + 1; // ditto
  894. int hasMoveStep = 0;
  895. if(checkXLoc!=editNode1->node_x || checkYLoc!=editNode1->node_y)
  896. {
  897. err_when(abs(checkXLoc-editNode1->node_x)>moveScale || abs(checkYLoc-editNode1->node_y)>moveScale);
  898. hasMoveStep += moveScale;
  899. checkXLoc = editNode1->node_x;
  900. checkYLoc = editNode1->node_y;
  901. }
  902. int i, j;
  903. int pathDist=0, found=0; // pathDist - counts the disitance of the generated path, found - whether a path to the surrounding is found
  904. int vecX, vecY, xMagn, yMagn, magn;
  905. #ifdef DEBUG
  906. int debugLoop1 = 0;
  907. int debugLoop2 = 0;
  908. #endif
  909. //------- find the first node that is on the surrounding of the object -------//
  910. for(i=1; i<result_node_count; ++i, editNode1++, editNode2++)
  911. {
  912. #ifdef DEBUG
  913. err_when(++debugLoop1>10000);
  914. #endif
  915. //------------ calculate parameters for checking ------------//
  916. vecX = editNode2->node_x - editNode1->node_x;
  917. vecY = editNode2->node_y - editNode1->node_y;
  918. err_when(vecX==0 && vecY==0);
  919. magn = ((xMagn=abs(vecX)) > (yMagn=abs(vecY))) ? xMagn : yMagn;
  920. if(xMagn)
  921. {
  922. vecX /= xMagn;
  923. vecX *= moveScale;
  924. }
  925. if(yMagn)
  926. {
  927. vecY /= yMagn;
  928. vecY *= moveScale;
  929. }
  930. err_when(abs(vecX)>moveScale && abs(vecY)>moveScale);
  931. #ifdef DEBUG
  932. debugLoop2 = 0;
  933. #endif
  934. //------------- check each location bewteen editNode1 and editNode2 -------------//
  935. for(j=0; j<magn; j+=moveScale)
  936. {
  937. #ifdef DEBUG
  938. err_when(++debugLoop2>10000);
  939. #endif
  940. checkXLoc += vecX;
  941. checkYLoc += vecY;
  942. if(checkXLoc>=xLoc1 && checkXLoc<=xLoc2 && checkYLoc>=yLoc1 && checkYLoc<=yLoc2)
  943. {
  944. found++;
  945. break;
  946. }
  947. }
  948. //-------------------------------------------------------------------------------//
  949. // a path is found, then set unit's parameters for its movement
  950. //-------------------------------------------------------------------------------//
  951. if(found)
  952. {
  953. editNode2->node_x = checkXLoc;
  954. editNode2->node_y = checkYLoc;
  955. if(i==1) // first editing
  956. {
  957. ResultNode *firstNodePtr = result_node_array;
  958. if(cur_x==firstNodePtr->node_x*ZOOM_LOC_WIDTH && cur_y==firstNodePtr->node_y*ZOOM_LOC_HEIGHT)
  959. {
  960. go_x = checkXLoc * ZOOM_LOC_WIDTH;
  961. go_y = checkYLoc * ZOOM_LOC_HEIGHT;
  962. }
  963. }
  964. pathDist += (j+moveScale);
  965. pathDist -= hasMoveStep;
  966. result_node_count = i+1;
  967. result_path_dist = pathDist;
  968. move_to_x_loc = checkXLoc;
  969. move_to_y_loc = checkYLoc;
  970. break;
  971. }
  972. else
  973. pathDist += magn;
  974. }
  975. return found;
  976. }
  977. //----------- End of function Unit::edit_path_to_surround -----------//
  978. //--------- Begin of function Unit::is_in_surrounding ---------//
  979. // Test whether the location (checkXLoc, checkYLoc) is in the surrounding of an object
  980. //
  981. // <int> checkXLoc, checkYLoc - location to check
  982. // <int> width - the width of the caller
  983. // <int> ObjectXLoc, objectYLoc - object location
  984. // <int> objectWidth - object width
  985. // <int> objectHeight - object height
  986. //
  987. // Note: assume the width and the height of the caller is equal
  988. // return 1 if in object surrounding
  989. // return 0 otherwise
  990. //
  991. int Unit::is_in_surrounding(int checkXLoc, int checkYLoc, int width, int objectXLoc, int objectYLoc,
  992. int objectWidth, int objectHeight)
  993. {
  994. switch(move_step_magn())
  995. {
  996. case 1:
  997. if(checkXLoc>=objectXLoc-width && checkXLoc<=objectXLoc+objectWidth &&
  998. checkYLoc>=objectYLoc-width && checkYLoc<=objectYLoc+objectHeight)
  999. return 1;
  1000. break;
  1001. case 2:
  1002. if(checkXLoc>=objectXLoc-width-1 && checkXLoc<=objectXLoc+objectWidth+1 &&
  1003. checkYLoc>=objectYLoc-width-1 && checkYLoc<=objectYLoc+objectHeight+1)
  1004. return 1;
  1005. break;
  1006. default: err_here();
  1007. break;
  1008. }
  1009. return 0;
  1010. }
  1011. //----------- End of function Unit::is_in_surrounding -----------//
  1012. //--------- Begin of function Unit::process_build_firm ---------//
  1013. // process action of building firms
  1014. //
  1015. void Unit::process_build_firm()
  1016. {
  1017. err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
  1018. err_when(action_x_loc<0 || action_x_loc>=MAX_WORLD_X_LOC || action_y_loc<0 || action_y_loc>=MAX_WORLD_Y_LOC);
  1019. err_when(action_x_loc<0 || action_x_loc>=MAX_WORLD_X_LOC);
  1020. err_when(action_y_loc<0 || action_y_loc>=MAX_WORLD_Y_LOC);
  1021. if( cur_action == SPRITE_IDLE ) // the unit is at the build location now
  1022. {
  1023. // **BUGHERE, the unit shouldn't be hidden when building structures
  1024. // otherwise, it's cargo_recno will be conflict with the structure's
  1025. // cargo_recno
  1026. int succeedFlag=0;
  1027. if( cur_x_loc()==move_to_x_loc && cur_y_loc()==move_to_y_loc )
  1028. {
  1029. FirmInfo *firmInfo = firm_res[action_para];
  1030. int width = firmInfo->loc_width;
  1031. int height = firmInfo->loc_height;
  1032. //---------------------------------------------------------//
  1033. // check whether the unit in the building surrounding
  1034. //---------------------------------------------------------//
  1035. if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc, width, height))
  1036. {
  1037. //---------- not in the building surrounding ---------//
  1038. return;
  1039. }
  1040. //---------------------------------------------------------//
  1041. // the unit in the firm surrounding
  1042. //---------------------------------------------------------//
  1043. Nation* nationPtr;
  1044. if(nation_recno)
  1045. {
  1046. nationPtr = nation_array[nation_recno];
  1047. if(nationPtr->cash < firmInfo->setup_cost)
  1048. return; // out of cash
  1049. }
  1050. else
  1051. nationPtr = NULL;
  1052. //---------------------------------------------------------//
  1053. // check whether the firm can be built in the specified location
  1054. //---------------------------------------------------------//
  1055. if( world.can_build_firm(action_x_loc, action_y_loc, action_para, sprite_recno) &&
  1056. firm_res[action_para]->can_build(sprite_recno) )
  1057. {
  1058. int aiUnit = ai_unit;
  1059. int actionXLoc = action_x_loc;
  1060. int actionYLoc = action_y_loc;
  1061. short unitRecno = sprite_recno;
  1062. //---------------------------------------------------------------------------//
  1063. // if unit inside the firm location, deinit the unit to free the space for
  1064. // building firm
  1065. //---------------------------------------------------------------------------//
  1066. if(move_to_x_loc>=action_x_loc && move_to_x_loc<action_x_loc+width &&
  1067. move_to_y_loc>=action_y_loc && move_to_y_loc<action_y_loc+height)
  1068. deinit_sprite(0); // 0-if the unit is currently selected, deactivate it.
  1069. if( firm_array.build_firm(action_x_loc, action_y_loc, nation_recno,
  1070. action_para, sprite_info->sprite_code, sprite_recno) ) // action_para = firm id.
  1071. {
  1072. //--------- able to the firm --------//
  1073. reset_action_para2();
  1074. succeedFlag = 1;
  1075. }
  1076. }
  1077. }
  1078. //----- call action finished/failure -----//
  1079. if( ai_action_id && nation_recno )
  1080. {
  1081. if( succeedFlag )
  1082. nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
  1083. else
  1084. nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
  1085. }
  1086. //---------------------------------------//
  1087. reset_action_para();
  1088. }
  1089. }
  1090. //----------- End of function Unit::process_build_firm -----------//
  1091. //--------- Begin of function Unit::process_assign ---------//
  1092. // process action of assigning
  1093. //
  1094. void Unit::process_assign()
  1095. {
  1096. err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
  1097. if(cur_action!=SPRITE_IDLE)
  1098. {
  1099. //------------------------------------------------------------------//
  1100. // change units' action if the firm/town/unit assign to has been deleted
  1101. // or has changed its nation
  1102. //------------------------------------------------------------------//
  1103. switch(action_mode2)
  1104. {
  1105. case ACTION_ASSIGN_TO_FIRM:
  1106. case ACTION_AUTO_DEFENSE_BACK_CAMP:
  1107. case ACTION_MONSTER_DEFEND_BACK_FIRM:
  1108. if(firm_array.is_deleted(action_para))
  1109. {
  1110. stop2();
  1111. return;
  1112. }
  1113. else
  1114. {
  1115. Firm *firmPtr = firm_array[action_para];
  1116. //###### begin trevor 21/6 #######//
  1117. if(firmPtr->nation_recno!=nation_recno && !firmPtr->can_assign_capture())
  1118. {
  1119. stop2();
  1120. return;
  1121. }
  1122. //###### end trevor 21/6 #######//
  1123. }
  1124. break;
  1125. case ACTION_ASSIGN_TO_TOWN:
  1126. case ACTION_DEFEND_TOWN_BACK_TOWN:
  1127. if(town_array.is_deleted(action_para))
  1128. {
  1129. stop2();
  1130. return;
  1131. }
  1132. else if(town_array[action_para]->nation_recno!=nation_recno)
  1133. {
  1134. stop2();
  1135. return;
  1136. }
  1137. break;
  1138. case ACTION_ASSIGN_TO_VEHICLE:
  1139. if(unit_array.is_deleted(action_para))
  1140. {
  1141. stop2();
  1142. return;
  1143. }
  1144. else if(unit_array[action_para]->nation_recno!=nation_recno)
  1145. {
  1146. stop2();
  1147. return;
  1148. }
  1149. break;
  1150. default: err_here();
  1151. break;
  1152. }
  1153. }
  1154. else //--------------- unit is idle -----------------//
  1155. {
  1156. if( cur_x_loc()==move_to_x_loc && cur_y_loc()==move_to_y_loc )
  1157. {
  1158. //----- first check if there is firm in the given location ------//
  1159. Location* locPtr = world.get_loc( action_x_loc, action_y_loc );
  1160. if( locPtr->is_firm() && locPtr->firm_recno() == action_para )
  1161. {
  1162. //---------------- a firm on the location -----------------//
  1163. Firm* firmPtr = firm_array[action_para];
  1164. FirmInfo *firmInfo = firm_res[firmPtr->firm_id];
  1165. //---------- resume action if the unit has not reached the firm surrounding ----------//
  1166. if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc,
  1167. firmInfo->loc_width, firmInfo->loc_height))
  1168. {
  1169. //------------ not in the surrounding -----------//
  1170. if(action_mode!=action_mode2) // for defense mode
  1171. set_move_to_surround(action_x_loc, action_y_loc, firmInfo->loc_width, firmInfo->loc_height, BUILDING_TYPE_FIRM_MOVE_TO);
  1172. return;
  1173. }
  1174. //------------ in the firm surrounding ------------//
  1175. if(!firmPtr->under_construction)
  1176. {
  1177. //-------------------------------------------------------//
  1178. // if in defense mode, update parameters in military camp
  1179. //-------------------------------------------------------//
  1180. if(action_mode2==ACTION_AUTO_DEFENSE_BACK_CAMP)
  1181. {
  1182. FirmCamp *campPtr = firmPtr->cast_to_FirmCamp();
  1183. campPtr->update_defense_unit(sprite_recno);
  1184. }
  1185. //---------------------------------------------------------------//
  1186. // remainder useful parameters to do reaction to Nation.
  1187. // These parameters will be destroyed after calling assign_unit()
  1188. //---------------------------------------------------------------//
  1189. int nationRecno = nation_recno;
  1190. short unitRecno = sprite_recno;
  1191. int actionXLoc = action_x_loc;
  1192. int actionYLoc = action_y_loc;
  1193. short aiActionId = ai_action_id;
  1194. char aiUnit = ai_unit;
  1195. reset_action_para2();
  1196. firmPtr->assign_unit(sprite_recno);
  1197. //----------------------------------------------------------//
  1198. // firm_array[]->assign_unit() must be done first. Then a
  1199. // town will be created and the reaction to build other firms
  1200. // requires the location of the town.
  1201. //----------------------------------------------------------//
  1202. if(aiActionId)
  1203. nation_array[nationRecno]->action_finished(aiActionId, unitRecno);
  1204. if( unit_array.is_deleted(unitRecno) )
  1205. return;
  1206. //--- else the firm is full, the unit's skill level is lower than those in firm, or no space to create town ---//
  1207. }
  1208. else
  1209. {
  1210. //---------- change the builder ------------//
  1211. if(ai_unit && firmPtr->under_construction)
  1212. return; // not allow AI to change firm builder
  1213. reset_action_para2();
  1214. if(skill.get_skill(SKILL_CONSTRUCTION) || skill.get_skill(firmPtr->firm_skill_id))
  1215. firmPtr->set_builder(sprite_recno);
  1216. }
  1217. //------------ update unit_array's selected parameters ------------//
  1218. reset_action_para();
  1219. if(selected_flag)
  1220. {
  1221. selected_flag = 0;
  1222. unit_array.selected_count--;
  1223. }
  1224. }
  1225. else if( locPtr->is_town() && locPtr->town_recno() == action_para )
  1226. {
  1227. //---------------- a town on the location -----------------//
  1228. if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc,
  1229. STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
  1230. {
  1231. //----------- not in the surrounding ------------//
  1232. return;
  1233. }
  1234. short actionPara = action_para;
  1235. short spriteRecno = sprite_recno;
  1236. if(ai_action_id)
  1237. nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno);
  1238. //------------ update unit_array's selected parameters ------------//
  1239. reset_action_para2();
  1240. reset_action_para();
  1241. if(selected_flag)
  1242. {
  1243. selected_flag = 0;
  1244. unit_array.selected_count--;
  1245. }
  1246. //-------------- assign the unit to the town -----------------//
  1247. town_array[actionPara]->assign_unit(spriteRecno);
  1248. }
  1249. //####### begin trevor 18/8 #########// the following code was called wrongly and causing bug
  1250. /*
  1251. //------ embarking a ground vehicle/animal ------//
  1252. else if(locPtr->has_unit(UNIT_LAND) && locPtr->unit_recno(UNIT_LAND) == action_para)
  1253. {
  1254. reset_action_para2();
  1255. reset_action_para();
  1256. if(selected_flag)
  1257. {
  1258. selected_flag = 0;
  1259. unit_array.selected_count--;
  1260. }
  1261. embark(action_para);
  1262. }
  1263. */
  1264. //####### end trevor 18/8 #########//
  1265. //------ embarking a sea vehicle/animal ------//
  1266. else if(locPtr->has_unit(UNIT_SEA) && locPtr->unit_recno(UNIT_SEA) == action_para)
  1267. {
  1268. //------------ update unit_array's selected parameters ------------//
  1269. reset_action_para2();
  1270. reset_action_para();
  1271. if(selected_flag)
  1272. {
  1273. selected_flag = 0;
  1274. unit_array.selected_count--;
  1275. }
  1276. //----------------- load the unit to the marine -----------------//
  1277. ((UnitMarine*)unit_array[action_para])->load_unit(sprite_recno);
  1278. }
  1279. else
  1280. {
  1281. //------------------------------------------------------------------//
  1282. // abort actions for ai_unit since the target location has nothing
  1283. //------------------------------------------------------------------//
  1284. if( ai_action_id )
  1285. nation_array[nation_recno]->action_failure(ai_action_id, sprite_recno);
  1286. }
  1287. }
  1288. //-***** don't place codes here as unit may be removed above *****-//
  1289. //reset_action_para();
  1290. //selected_flag = 0;
  1291. }
  1292. }
  1293. //----------- End of function Unit::process_assign -----------//
  1294. //--------- Begin of function Unit::process_burn ---------//
  1295. // process action of burning to a specified location
  1296. //
  1297. void Unit::process_burn()
  1298. {
  1299. err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
  1300. if( cur_action == SPRITE_IDLE ) // the unit is at the build location now
  1301. {
  1302. if( next_x_loc()==action_x_loc && next_y_loc()==action_y_loc )
  1303. {
  1304. reset_action_para2();
  1305. set_dir(move_to_x_loc, move_to_y_loc, action_x_loc, action_y_loc);
  1306. world.setup_fire( action_x_loc, action_y_loc );
  1307. }
  1308. reset_action_para();
  1309. }
  1310. }
  1311. //----------- End of function Unit::process_burn -----------//
  1312. //--------- Begin of function Unit::process_settle ---------//
  1313. // process action of settling to an existing town
  1314. //
  1315. void Unit::process_settle()
  1316. {
  1317. err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1);
  1318. if( cur_action == SPRITE_IDLE ) // the unit is at the build location now
  1319. {
  1320. reset_path();
  1321. if( cur_x_loc()==move_to_x_loc && cur_y_loc()==move_to_y_loc )
  1322. {
  1323. if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc, action_y_loc,
  1324. STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
  1325. return;
  1326. Location* locPtr = world.get_loc(action_x_loc, action_y_loc);
  1327. if(!locPtr->is_town())
  1328. {
  1329. //##### begin trevor 1/9 ########//
  1330. int unitRecno = sprite_recno;
  1331. reset_action_para2();
  1332. //------------ settle the unit now -------------//
  1333. town_array.settle(sprite_recno, action_x_loc, action_y_loc);
  1334. if( unit_array.is_deleted(unitRecno) )
  1335. return;
  1336. reset_action_para();
  1337. //##### end trevor 1/9 ########//
  1338. }
  1339. else if(town_array[locPtr->town_recno()]->nation_recno == nation_recno)
  1340. {
  1341. //---------- a town zone already exists ---------//
  1342. assign(action_x_loc, action_y_loc);
  1343. return;
  1344. }
  1345. }
  1346. else
  1347. reset_action_para();
  1348. }
  1349. }
  1350. //----------- End of function Unit::process_settle -----------//
  1351. //--------- Begin of function Unit::go_cast_power ---------//
  1352. // do action of god casting
  1353. //
  1354. void Unit::go_cast_power(int castXLoc, int castYLoc, char castPowerType, char remoteAction)
  1355. {
  1356. err_when(mobile_type!=UNIT_AIR);
  1357. //----------------------------------------------------------------//
  1358. // return if the unit is dead
  1359. //----------------------------------------------------------------//
  1360. if(hit_points<=0 || action_mode==ACTION_DIE || cur_action==SPRITE_DIE)
  1361. return;
  1362. if(!remoteAction && remote.is_enable() )
  1363. {
  1364. //------------ process multiplayer calling ---------------//
  1365. // packet structure : <unit recno> <xLoc> <yLoc> <power type>
  1366. short *shortPtr =(short *)remote.new_send_queue_msg(MSG_U_GOD_CAST, 4*sizeof(short) );
  1367. shortPtr[0] = sprite_recno;
  1368. shortPtr[1] = castXLoc;
  1369. shortPtr[2] = castYLoc;
  1370. shortPtr[3] = castPowerType;
  1371. return;
  1372. }
  1373. UnitGod *unitGod = (UnitGod *)this;
  1374. //----------------------------------------------------------------//
  1375. // action_mode2: checking for equal action or idle action
  1376. //----------------------------------------------------------------//
  1377. if(action_mode2==ACTION_GO_CAST_POWER && action_para2==0 && action_x_loc2==castXLoc && action_y_loc2==castYLoc
  1378. && unitGod->cast_power_type==castPowerType)
  1379. {
  1380. if(cur_action!=SPRITE_IDLE)
  1381. return;
  1382. }
  1383. else
  1384. {
  1385. //----------------------------------------------------------------//
  1386. // action_mode2: store new order
  1387. //----------------------------------------------------------------//
  1388. action_mode2 = ACTION_GO_CAST_POWER;
  1389. action_para2 = 0;
  1390. action_x_loc2 = castXLoc;
  1391. action_y_loc2 = castYLoc;
  1392. }
  1393. //----- order the sprite to stop as soon as possible -----//
  1394. stop(); // new order
  1395. //------------- do searching if neccessary -------------//
  1396. if(m.points_distance(next_x_loc(), next_y_loc(), castXLoc, castYLoc)>DO_CAST_POWER_RANGE)
  1397. search(castXLoc, castYLoc, 1);
  1398. //----------- set action to build the firm -----------//
  1399. action_mode = ACTION_GO_CAST_POWER;
  1400. action_para = 0;
  1401. action_x_loc = castXLoc;
  1402. action_y_loc = castYLoc;
  1403. unitGod->cast_power_type = castPowerType;
  1404. unitGod->cast_origin_x = next_x_loc();
  1405. unitGod->cast_origin_y = next_y_loc();
  1406. unitGod->cast_target_x = castXLoc;
  1407. unitGod->cast_target_y = castYLoc;
  1408. }
  1409. //----------- End of function Unit::go_cast_power -----------//
  1410. //--------- Begin of function Unit::process_go_cast_power ---------//
  1411. // process action of god casting
  1412. //
  1413. void Unit::process_go_cast_power()
  1414. {
  1415. err_when(mobile_type!=UNIT_AIR);
  1416. err_when(action_x_loc2<0 || action_x_loc2>=MAX_WORLD_X_LOC);
  1417. err_when(action_y_loc2<0 || action_y_loc2>=MAX_WORLD_Y_LOC);
  1418. UnitGod *unitGod = (UnitGod *)this;
  1419. if(cur_action==SPRITE_IDLE)
  1420. {
  1421. //----------------------------------------------------------------------------------------//
  1422. // Checking condition to do casting power, Or resume action
  1423. //----------------------------------------------------------------------------------------//
  1424. if(m.points_distance(cur_x_loc(), cur_y_loc(), action_x_loc2, action_y_loc2)<=DO_CAST_POWER_RANGE)
  1425. {
  1426. if( next_x_loc() != action_x_loc2 ||
  1427. next_y_loc() != action_y_loc2 )
  1428. {
  1429. set_dir(next_x_loc(), next_y_loc(), action_x_loc2, action_y_loc2);
  1430. }
  1431. set_attack(); // set cur_action=sprite_attack to cast power
  1432. cur_frame = 1;
  1433. }
  1434. else
  1435. {
  1436. err_when(action_mode2!=ACTION_GO_CAST_POWER || action_para2);
  1437. go_cast_power(action_x_loc2, action_y_loc2, unitGod->cast_power_type, COMMAND_AUTO);
  1438. }
  1439. }
  1440. else if(cur_action==SPRITE_ATTACK)
  1441. {
  1442. //----------------------------------------------------------------------------------------//
  1443. // do casting power now
  1444. //----------------------------------------------------------------------------------------//
  1445. AttackInfo *attackInfo = attack_info_array + cur_attack;
  1446. if(cur_frame == attackInfo->bullet_out_frame)
  1447. {
  1448. // add effect
  1449. add_close_attack_effect();
  1450. unitGod->cast_power(action_x_loc2, action_y_loc2);
  1451. set_remain_attack_delay();
  1452. // stop2();
  1453. }
  1454. if( cur_frame == 1 && remain_attack_delay == 0 ) // last frame of delaying
  1455. stop2();
  1456. }
  1457. }
  1458. //----------- End of function Unit::process_go_cast_power -----------//