OUNITD.cpp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144
  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 : OUNITD.CPP
  21. //Description : Object Unit defense functions
  22. //Owner : Alex
  23. #include <ALL.h>
  24. #include <OUNIT.h>
  25. #include <OWORLD.h>
  26. #include <OFIRM.h>
  27. #include <ONATION.h>
  28. #include <OTOWN.h>
  29. #include <OF_CAMP.h>
  30. #include <OF_MONS.h>
  31. #ifdef NO_DEBUG_UNIT
  32. #undef err_when
  33. #undef err_here
  34. #undef err_if
  35. #undef err_else
  36. #undef err_now
  37. #define err_when(cond)
  38. #define err_here()
  39. #define err_if(cond)
  40. #define err_else
  41. #define err_now(msg)
  42. #undef DEBUG
  43. #endif
  44. //=================================================================================================//
  45. // Unit's defend mode generalized functions
  46. //=================================================================================================//
  47. //--------- Begin of function Unit::in_any_defense_mode ---------//
  48. // check whether the unit is in defense mode
  49. //
  50. // return 1 if it is
  51. // return 0 otherwise
  52. //
  53. int Unit::in_any_defense_mode()
  54. {
  55. return (action_mode2>=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2<=ACTION_MONSTER_DEFEND_BACK_FIRM);
  56. }
  57. //----------- End of function Unit::in_any_defense_mode -----------//
  58. //--------- Begin of function Unit::general_defend_mode_detect_target ---------//
  59. // call the appropriate defend function for the current type of defend
  60. //
  61. // <int> checkDefendMode - flag to check defend mode or not
  62. //
  63. void Unit::general_defend_mode_detect_target(int checkDefendMode)
  64. {
  65. stop();
  66. switch(action_mode2)
  67. {
  68. case ACTION_AUTO_DEFENSE_ATTACK_TARGET:
  69. defense_detect_target();
  70. break;
  71. case ACTION_DEFEND_TOWN_ATTACK_TARGET:
  72. defend_town_detect_target();
  73. break;
  74. case ACTION_MONSTER_DEFEND_ATTACK_TARGET:
  75. monster_defend_detect_target();
  76. break;
  77. default: if(checkDefendMode)
  78. err_here();
  79. break;
  80. }
  81. }
  82. //----------- End of function Unit::general_defend_mode_detect_target -----------//
  83. //--------- Begin of function Unit::general_defend_mode_process_attack_target ---------//
  84. // process unit defense action. If target is dead, action_mode changes to detect_mode
  85. //
  86. // return 1 if action mode changes to detect mode
  87. // return 0 otherwise
  88. //
  89. int Unit::general_defend_mode_process_attack_target()
  90. {
  91. Location *locPtr;
  92. Unit *unitPtr;
  93. Town *townPtr;
  94. Firm *firmPtr;
  95. SpriteInfo *spriteInfo;
  96. FirmInfo *firmInfo;
  97. int clearToDetect = 0;
  98. //------------------------------------------------------------------------------//
  99. // if the unit's action mode is in defensive attack action, process the corresponding
  100. // checking.
  101. //------------------------------------------------------------------------------//
  102. switch(action_mode)
  103. {
  104. case ACTION_ATTACK_UNIT:
  105. if(unit_array.is_deleted(action_para2))
  106. clearToDetect++;
  107. else
  108. {
  109. err_when(unit_array.is_deleted(action_para2));
  110. unitPtr = unit_array[action_para2];
  111. //if(unitPtr->cur_action==SPRITE_IDLE)
  112. // clearToDetect++;
  113. if(!nation_can_attack(unitPtr->nation_recno)) // cannot attack this nation
  114. clearToDetect++;
  115. }
  116. break;
  117. case ACTION_ATTACK_FIRM:
  118. if(firm_array.is_deleted(action_para2))
  119. clearToDetect++;
  120. else
  121. {
  122. err_when(firm_array.is_deleted(action_para2));
  123. firmPtr = firm_array[action_para2];
  124. if(!nation_can_attack(firmPtr->nation_recno)) // cannot attack this nation
  125. clearToDetect++;
  126. }
  127. break;
  128. case ACTION_ATTACK_TOWN:
  129. if(town_array.is_deleted(action_para2))
  130. clearToDetect++;
  131. else
  132. {
  133. err_when(town_array.is_deleted(action_para2));
  134. townPtr = town_array[action_para2];
  135. if(!nation_can_attack(townPtr->nation_recno)) // cannot attack this nation
  136. clearToDetect++;
  137. }
  138. break;
  139. case ACTION_ATTACK_WALL:
  140. locPtr = world.get_loc(action_x_loc2, action_y_loc2);
  141. if(!locPtr->is_wall() || !nation_can_attack(locPtr->power_nation_recno))
  142. clearToDetect++;
  143. break;
  144. default: clearToDetect++;
  145. break;
  146. }
  147. //------------------------------------------------------------------------------//
  148. // suitation changed to defensive detecting mode
  149. //------------------------------------------------------------------------------//
  150. if(clearToDetect)
  151. {
  152. //----------------------------------------------------------//
  153. // target is dead, change to detect state for another target
  154. //----------------------------------------------------------//
  155. reset_action_para();
  156. return 1;
  157. }
  158. else if(waiting_term<ATTACK_WAITING_TERM)
  159. waiting_term++;
  160. else
  161. {
  162. //------------------------------------------------------------------------------//
  163. // process the corresponding attacking procedure.
  164. //------------------------------------------------------------------------------//
  165. waiting_term = 0;
  166. switch(action_mode)
  167. {
  168. case ACTION_ATTACK_UNIT:
  169. err_when(unit_array.is_deleted(action_para2) || !unitPtr);
  170. spriteInfo = unitPtr->sprite_info;
  171. //-----------------------------------------------------------------//
  172. // attack the target if able to reach the target surrounding, otherwise
  173. // continue to wait
  174. //-----------------------------------------------------------------//
  175. action_x_loc2 = unitPtr->next_x_loc(); // update target location
  176. action_y_loc2 = unitPtr->next_y_loc();
  177. if(space_for_attack(action_x_loc2, action_y_loc2, unitPtr->mobile_type, spriteInfo->loc_width, spriteInfo->loc_height))
  178. attack_unit(unitPtr->sprite_recno);
  179. break;
  180. case ACTION_ATTACK_FIRM:
  181. err_when(firm_array.is_deleted(action_para2) || !firmPtr);
  182. firmInfo = firm_res[firmPtr->firm_id];
  183. //-----------------------------------------------------------------//
  184. // attack the target if able to reach the target surrounding, otherwise
  185. // continue to wait
  186. //-----------------------------------------------------------------//
  187. attack_firm(action_x_loc2, action_y_loc2);
  188. if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2,
  189. firmInfo->loc_width, firmInfo->loc_height))
  190. waiting_term = 0;
  191. break;
  192. case ACTION_ATTACK_TOWN:
  193. err_when(town_array.is_deleted(action_para2) || !townPtr);
  194. //-----------------------------------------------------------------//
  195. // attack the target if able to reach the target surrounding, otherwise
  196. // continue to wait
  197. //-----------------------------------------------------------------//
  198. attack_town(action_x_loc2, action_y_loc2);
  199. if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2,
  200. STD_TOWN_LOC_WIDTH, STD_TOWN_LOC_HEIGHT))
  201. waiting_term = 0;
  202. break;
  203. case ACTION_ATTACK_WALL:
  204. err_when(action_para || action_para2);
  205. attack_wall(action_x_loc2, action_y_loc2);
  206. if(!is_in_surrounding(move_to_x_loc, move_to_y_loc, sprite_info->loc_width, action_x_loc2, action_y_loc2, 1, 1))
  207. waiting_term = 0;
  208. break;
  209. default:
  210. err_here();
  211. break;
  212. }
  213. }
  214. return 0;
  215. }
  216. //----------- End of function Unit::general_defend_mode_process_attack_target -----------//
  217. //=================================================================================================//
  218. // Unit's defense mode
  219. //=================================================================================================//
  220. //--------- Begin of function Unit::defense_attack_unit ---------//
  221. // defensive attack units
  222. //
  223. // <short> targetRecno - recno of the target
  224. //
  225. void Unit::defense_attack_unit(short targetRecno)
  226. {
  227. action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET;
  228. attack_unit(targetRecno);
  229. }
  230. //----------- End of function Unit::defense_attack_unit -----------//
  231. //--------- Begin of function Unit::defense_attack_firm ---------//
  232. // defensive attack firm
  233. //
  234. // <short> targetXLoc - x location of the firm
  235. // <short> targetYLoc - y location of the firm
  236. //
  237. void Unit::defense_attack_firm(int targetXLoc, int targetYLoc)
  238. {
  239. action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET;
  240. attack_firm(targetXLoc, targetYLoc);
  241. }
  242. //----------- End of function Unit::defense_attack_firm -----------//
  243. //--------- Begin of function Unit::defense_attack_town ---------//
  244. // defensive attack town
  245. //
  246. // <short> targetXLoc - x location of the town
  247. // <short> targetYLoc - y location of the town
  248. //
  249. void Unit::defense_attack_town(int targetXLoc, int targetYLoc)
  250. {
  251. action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET;
  252. attack_town(targetXLoc, targetYLoc);
  253. }
  254. //----------- End of function Unit::defense_attack_town -----------//
  255. //--------- Begin of function Unit::defense_attack_wall ---------//
  256. // defensive attack wall
  257. //
  258. // <short> targetXLoc - x location of wall
  259. // <short> targetYLoc - y location of wall
  260. //
  261. void Unit::defense_attack_wall(int targetXLoc, int targetYLoc)
  262. {
  263. action_mode2 = ACTION_AUTO_DEFENSE_ATTACK_TARGET;
  264. attack_wall(targetXLoc, targetYLoc);
  265. }
  266. //----------- End of function Unit::defense_attack_wall -----------//
  267. //--------- Begin of function Unit::defense_detect_target ---------//
  268. // set parameters for unit's defensive mode
  269. //
  270. void Unit::defense_detect_target()
  271. {
  272. action_mode2 = ACTION_AUTO_DEFENSE_DETECT_TARGET;
  273. action_para2 = AUTO_DEFENSE_DETECT_COUNT;
  274. action_x_loc2 = -1;
  275. action_y_loc2 = -1;
  276. }
  277. //----------- End of function Unit::defense_detect_target -----------//
  278. //--------- Begin of function Unit::defense_back_camp ---------//
  279. // set parameters for unit's to return camp
  280. //
  281. // <int> firmXLoc - x location of the firm
  282. // <int> firmYLoc - y location of the firm
  283. //
  284. void Unit::defense_back_camp(int firmXLoc, int firmYLoc)
  285. {
  286. err_when(firm_array[world.get_loc(firmXLoc, firmYLoc)->firm_recno()]->firm_id!=FIRM_CAMP);
  287. err_when(firm_array[world.get_loc(firmXLoc, firmYLoc)->firm_recno()]->firm_recno!=action_misc_para);
  288. assign(firmXLoc, firmYLoc);
  289. action_mode2 = ACTION_AUTO_DEFENSE_BACK_CAMP;
  290. }
  291. //----------- End of function Unit::defense_back_camp -----------//
  292. //--------- Begin of function Unit::process_auto_defense_attack_target ---------//
  293. // process the action for unit's defensive attack
  294. //
  295. void Unit::process_auto_defense_attack_target()
  296. {
  297. err_when(action_mode2!=ACTION_AUTO_DEFENSE_ATTACK_TARGET);
  298. if(general_defend_mode_process_attack_target())
  299. {
  300. defense_detect_target();
  301. err_when(action_mode!=ACTION_STOP || action_para || action_x_loc!=-1 || action_y_loc!=-1 || cur_action==SPRITE_ATTACK);
  302. }
  303. }
  304. //----------- End of function Unit::process_auto_defense_attack_target -----------//
  305. //--------- Begin of function Unit::process_auto_defense_detect_target ---------//
  306. // process action for unit's defensive detecet target
  307. //
  308. void Unit::process_auto_defense_detect_target()
  309. {
  310. err_when(action_mode2!=ACTION_AUTO_DEFENSE_DETECT_TARGET);
  311. err_when(action_mode!=ACTION_STOP);
  312. err_when(action_para!=0);
  313. err_when(action_x_loc!=-1 || action_y_loc!=-1 || action_x_loc!=-1 || action_y_loc2!=-1);
  314. //----------------------------------------------------------------//
  315. // no target or target is out of detect range, so change state to
  316. // back camp
  317. //----------------------------------------------------------------//
  318. if(!action_para2)
  319. {
  320. err_when(action_misc!=ACTION_MISC_DEFENSE_CAMP_RECNO || !action_misc_para);
  321. int back = 0;
  322. FirmCamp *campPtr;
  323. Unit *targetPtr;
  324. if(firm_array.is_deleted(action_misc_para))
  325. back++;
  326. else
  327. {
  328. campPtr = (FirmCamp*) firm_array[action_misc_para];
  329. if(unit_array.is_deleted(campPtr->defend_target_recno))
  330. back++;
  331. else
  332. {
  333. targetPtr = unit_array[campPtr->defend_target_recno];
  334. if(targetPtr->action_mode!=ACTION_ATTACK_FIRM || targetPtr->action_para!=campPtr->firm_recno)
  335. back++;
  336. }
  337. }
  338. if(!back)
  339. {
  340. //action_mode2 = ACTION_AUTO_DEFENSE_DETECT_TARGET;
  341. action_para2 = AUTO_DEFENSE_DETECT_COUNT;
  342. return;
  343. }
  344. process_auto_defense_back_camp();
  345. return;
  346. }
  347. //----------------------------------------------------------------//
  348. // defense_detecting target algorithm
  349. //----------------------------------------------------------------//
  350. int startLoc;
  351. int dimension;
  352. switch(action_para2%GAME_FRAMES_PER_DAY)
  353. {
  354. case 3: startLoc = 2;// 1-7, check 224 = 15^2-1
  355. //### begin alex 3/10 ###//
  356. dimension = 7;
  357. //#### end alex 3/10 ####//
  358. break;
  359. case 2: startLoc = 122;// 6-8, check 168 = 17^2-11^2
  360. dimension = 8;
  361. break;
  362. case 1: startLoc = 170;// 7-9, check 192 = 19^2-13^2
  363. dimension = EFFECTIVE_AUTO_DEFENSE_DISTANCE;
  364. break;
  365. default: action_para2--;
  366. return;
  367. }
  368. //---------------------------------------------------------------//
  369. // attack the target if target detected, or change the detect region
  370. //---------------------------------------------------------------//
  371. if(!idle_detect_attack(startLoc, dimension, 1)) // defense mode is on
  372. action_para2--;
  373. }
  374. //----------- End of function Unit::process_auto_defense_detect_target -----------//
  375. //--------- Begin of function Unit::process_auto_defense_back_camp ---------//
  376. // process action for the units to return camp
  377. //
  378. void Unit::process_auto_defense_back_camp()
  379. {
  380. int clearDefenseMode = 0;
  381. if(action_mode!=ACTION_ASSIGN_TO_FIRM) // the unit may become idle or unable to reach firm, reactivate it
  382. {
  383. Firm *firmPtr;
  384. if(action_misc!=ACTION_MISC_DEFENSE_CAMP_RECNO || !action_misc_para || firm_array.is_deleted(action_misc_para))
  385. clearDefenseMode++;
  386. else
  387. {
  388. firmPtr = firm_array[action_misc_para];
  389. if(firmPtr->firm_id!=FIRM_CAMP || firmPtr->nation_recno!=nation_recno)
  390. clearDefenseMode++;
  391. else
  392. {
  393. defense_back_camp(firmPtr->loc_x1, firmPtr->loc_y1); // go back to the military camp
  394. err_when(action_mode2!=ACTION_AUTO_DEFENSE_BACK_CAMP);
  395. return;
  396. }
  397. }
  398. }
  399. else if(cur_action==SPRITE_IDLE)
  400. {
  401. if(firm_array.is_deleted(action_misc_para))
  402. clearDefenseMode++;
  403. else
  404. {
  405. Firm *firmPtr = firm_array[action_misc_para];
  406. defense_back_camp(firmPtr->loc_x1, firmPtr->loc_y1);
  407. err_when(action_mode2!=ACTION_AUTO_DEFENSE_BACK_CAMP);
  408. return;
  409. }
  410. }
  411. err_when(!clearDefenseMode);
  412. //----------------------------------------------------------------//
  413. // clear order if the camp is deleted
  414. //----------------------------------------------------------------//
  415. stop2();
  416. reset_action_misc_para();
  417. err_when(in_auto_defense_mode());
  418. }
  419. //----------- End of function Unit::process_auto_defense_back_camp -----------//
  420. //------------- Begin of function Unit::in_auto_defense_mode --------------//
  421. // check whether the units in auto defense mode
  422. //
  423. int Unit::in_auto_defense_mode()
  424. {
  425. return (action_mode2>=ACTION_AUTO_DEFENSE_ATTACK_TARGET && action_mode2<=ACTION_AUTO_DEFENSE_BACK_CAMP);
  426. }
  427. //----------- End of function Unit::in_auto_defense_mode -----------//
  428. //------------- Begin of function Unit::defense_follow_target --------------//
  429. // decide whether to follow the target
  430. //
  431. // return 0 if aborting attack the current target and go back to military camp
  432. // return 1 otherwise
  433. //
  434. int Unit::defense_follow_target()
  435. {
  436. #define PROB_HOSTILE_RETURN 10
  437. #define PROB_FRIENDLY_RETURN 20
  438. #define PROB_NEUTRAL_RETURN 30
  439. if(unit_array.is_deleted(action_para))
  440. return 1;
  441. if(cur_action==SPRITE_ATTACK)
  442. return 1;
  443. Unit *targetPtr = unit_array[action_para];
  444. Location *locPtr = world.get_loc(action_x_loc, action_y_loc);
  445. if(!locPtr->has_unit(targetPtr->mobile_type))
  446. return 1; // the target may be dead or invisible
  447. int returnFactor, abortAction = 0;
  448. //-----------------------------------------------------------------//
  449. // calculate the chance to go back to military camp in following the
  450. // target
  451. //-----------------------------------------------------------------//
  452. if(locPtr->power_nation_recno==nation_recno)
  453. return 1; // target within our nation
  454. else if(!locPtr->power_nation_recno) // is neutral
  455. returnFactor = PROB_NEUTRAL_RETURN;
  456. else
  457. {
  458. Nation *locNationPtr = nation_array[locPtr->power_nation_recno];
  459. if(locNationPtr->get_relation_status(nation_recno)==NATION_HOSTILE)
  460. returnFactor = PROB_HOSTILE_RETURN;
  461. else
  462. returnFactor = PROB_FRIENDLY_RETURN;
  463. }
  464. if(!abortAction)
  465. {
  466. SpriteInfo *targetSpriteInfo = targetPtr->sprite_info;
  467. //-----------------------------------------------------------------//
  468. // if the target moves faster than this unit, it is more likely for
  469. // this unit to go back to military camp.
  470. //-----------------------------------------------------------------//
  471. //-**** should also consider the combat level and hit_points of both unit ****-//
  472. if(targetSpriteInfo->speed > sprite_info->speed)
  473. returnFactor -= 5;
  474. if(m.random(returnFactor)==0) // return to camp if true
  475. abortAction++;
  476. else
  477. return 1;
  478. }
  479. err_when(!abortAction);
  480. err_when(action_mode==ACTION_ASSIGN_TO_FIRM); // if so, process_auto_defense_back_camp() cannot process successfully
  481. process_auto_defense_back_camp();
  482. return 0; // cancel attack
  483. }
  484. //----------- End of function Unit::defense_follow_target -----------//
  485. //------------- Begin of function Unit::clear_unit_defense_mode --------------//
  486. // clear defensive mode
  487. //
  488. void Unit::clear_unit_defense_mode()
  489. {
  490. //------- cancel defense mode and continue the current action -------//
  491. action_mode2 = action_mode;
  492. action_para2 = action_para;
  493. action_x_loc2 = action_x_loc;
  494. action_y_loc2 = action_y_loc;
  495. reset_action_misc_para();
  496. if( unit_mode == UNIT_MODE_DEFEND_TOWN )
  497. set_mode(0); // reset unit mode
  498. }
  499. //----------------- End of function Unit::clear_unit_defense_mode ----------------//
  500. //=================================================================================================//
  501. // Town unit's defend mode, eg rebel
  502. //=================================================================================================//
  503. //--------- Begin of function Unit::defend_town_attack_unit ---------//
  504. // set to defensive mode
  505. //
  506. // <short> targetRecno - record of target
  507. //
  508. void Unit::defend_town_attack_unit(short targetRecno)
  509. {
  510. action_mode2 = ACTION_DEFEND_TOWN_ATTACK_TARGET;
  511. attack_unit(targetRecno);
  512. }
  513. //----------- End of function Unit::defend_town_attack_unit -----------//
  514. //------------- Begin of function Unit::defend_town_detect_target --------------//
  515. // set to detect mode
  516. //
  517. void Unit::defend_town_detect_target()
  518. {
  519. action_mode2 = ACTION_DEFEND_TOWN_DETECT_TARGET;
  520. action_para2 = UNIT_DEFEND_TOWN_DETECT_COUNT;
  521. action_x_loc2 = -1;
  522. action_y_loc2 = -1;
  523. }
  524. //----------- End of function Unit::defend_town_detect_target -----------//
  525. //------------- Begin of function Unit::process_defend_town_attack_target --------------//
  526. // defend town units is only allowed to attack unit
  527. //
  528. void Unit::process_defend_town_attack_target()
  529. {
  530. err_when(action_mode2!=ACTION_DEFEND_TOWN_ATTACK_TARGET);
  531. if(general_defend_mode_process_attack_target())
  532. {
  533. action_mode2 = ACTION_DEFEND_TOWN_DETECT_TARGET;
  534. action_para2 = UNIT_DEFEND_TOWN_DETECT_COUNT;
  535. action_x_loc2 = action_y_loc2 = -1;
  536. err_when(action_mode!=ACTION_STOP || action_para || action_x_loc!=-1 || action_y_loc!=-1 || cur_action==SPRITE_ATTACK);
  537. }
  538. }
  539. //----------------- End of function Unit::process_defend_town_attack_target ----------------//
  540. //------------- Begin of function Unit::process_defend_town_detect_target --------------//
  541. // process detect mode
  542. //
  543. void Unit::process_defend_town_detect_target()
  544. {
  545. err_when(action_mode2!=ACTION_DEFEND_TOWN_DETECT_TARGET);
  546. err_when(action_mode!=ACTION_STOP);
  547. err_when(action_para!=0);
  548. err_when(action_x_loc!=-1 || action_y_loc!=-1 || action_x_loc2!=-1 || action_y_loc2!=-1);
  549. //----------------------------------------------------------------//
  550. // no target or target is out of detect range, so change state to
  551. // back camp
  552. //----------------------------------------------------------------//
  553. if(!action_para2)
  554. {
  555. err_when(action_misc!=ACTION_MISC_DEFEND_TOWN_RECNO || !action_misc_para);
  556. err_when(unit_mode!=UNIT_MODE_DEFEND_TOWN || !unit_mode_para);
  557. int back = 0;
  558. Town *townPtr;
  559. Unit *targetPtr;
  560. if(town_array.is_deleted(action_misc_para))
  561. back++;
  562. else
  563. {
  564. townPtr = town_array[action_misc_para];
  565. if(unit_array.is_deleted(townPtr->defend_target_recno))
  566. back++;
  567. else
  568. {
  569. targetPtr = unit_array[townPtr->defend_target_recno];
  570. if(targetPtr->action_mode!=ACTION_ATTACK_TOWN || targetPtr->action_para!=townPtr->town_recno)
  571. back++;
  572. }
  573. }
  574. if(!back)
  575. {
  576. //action_mode2 = ACTION_DEFEND_TOWN_DETECT_TARGET;
  577. action_para2 = UNIT_DEFEND_TOWN_DETECT_COUNT;
  578. return;
  579. }
  580. process_defend_town_back_town();
  581. return;
  582. }
  583. //----------------------------------------------------------------//
  584. // defense_detecting target algorithm
  585. //----------------------------------------------------------------//
  586. int startLoc;
  587. int dimension;
  588. switch(action_para2%GAME_FRAMES_PER_DAY)
  589. {
  590. case 3: startLoc = 2;// 1-7, check 224 = 15^2-1
  591. //### begin alex 3/10 ###//
  592. dimension = 7;
  593. //#### end alex 3/10 ####//
  594. break;
  595. case 2: startLoc = 122;// 6-8, check 168 = 17^2-11^2
  596. dimension = 8;
  597. break;
  598. case 1: startLoc = 170;// 7-9, check 192 = 19^2-13^2
  599. dimension = EFFECTIVE_DEFEND_TOWN_DISTANCE;
  600. break;
  601. default: action_para2--;
  602. return;
  603. }
  604. //---------------------------------------------------------------//
  605. // attack the target if target detected, or change the detect region
  606. //---------------------------------------------------------------//
  607. if(!idle_detect_attack(startLoc, dimension, 1)) // defense mode is on
  608. action_para2--;
  609. }
  610. //----------------- End of function Unit::process_defend_town_detect_target ----------------//
  611. //------------- Begin of function Unit::process_defend_town_back_town --------------//
  612. // process action to go back town
  613. //
  614. void Unit::process_defend_town_back_town()
  615. {
  616. int clearDefenseMode = 0;
  617. if(action_mode!=ACTION_ASSIGN_TO_TOWN) // the unit may become idle or unable to reach town, reactivate it
  618. {
  619. Town *townPtr;
  620. if(action_misc!=ACTION_MISC_DEFEND_TOWN_RECNO || !action_misc_para || town_array.is_deleted(action_misc_para))
  621. clearDefenseMode++;
  622. else
  623. {
  624. townPtr = town_array[action_misc_para];
  625. if(townPtr->nation_recno!=nation_recno)
  626. clearDefenseMode++;
  627. else
  628. {
  629. defend_town_back_town(action_misc_para); // go back to the town
  630. err_when(action_mode2!=ACTION_DEFEND_TOWN_BACK_TOWN);
  631. return;
  632. }
  633. }
  634. }
  635. else if(cur_action==SPRITE_IDLE)
  636. {
  637. if(town_array.is_deleted(action_misc_para))
  638. clearDefenseMode++;
  639. else
  640. {
  641. defend_town_back_town(action_misc_para);
  642. err_when(action_mode2!=ACTION_DEFEND_TOWN_BACK_TOWN);
  643. return;
  644. }
  645. }
  646. err_when(!clearDefenseMode);
  647. //----------------------------------------------------------------//
  648. // clear order if the town is deleted
  649. //----------------------------------------------------------------//
  650. stop2();
  651. reset_action_misc_para();
  652. err_when(in_defend_town_mode());
  653. }
  654. //----------------- End of function Unit::process_defend_town_back_town ----------------//
  655. //------------- Begin of function Unit::in_defend_town_mode --------------//
  656. // check whether the unit is in defend town mode
  657. //
  658. int Unit::in_defend_town_mode()
  659. {
  660. return (action_mode2>=ACTION_DEFEND_TOWN_ATTACK_TARGET && action_mode2<=ACTION_DEFEND_TOWN_BACK_TOWN);
  661. }
  662. //----------------- End of function Unit::in_defend_town_mode ----------------//
  663. //--------- Begin of function Unit::defend_town_back_town ---------//
  664. // set action to back town
  665. //
  666. // <int> townRecno - recno of the town
  667. //
  668. void Unit::defend_town_back_town(short townRecno)
  669. {
  670. err_when(town_array.is_deleted(townRecno));
  671. Town *townPtr = town_array[townRecno];
  672. assign(townPtr->loc_x1, townPtr->loc_y1);
  673. action_mode2 = ACTION_DEFEND_TOWN_BACK_TOWN;
  674. }
  675. //----------- End of function Unit::defend_town_back_town -----------//
  676. //------------- Begin of function Unit::defend_town_follow_target --------------//
  677. // check the unit should follow the target or not
  678. //
  679. // return 0 if aborting attack the current target and go back to military camp
  680. // return 1 otherwise
  681. //
  682. int Unit::defend_town_follow_target()
  683. {
  684. err_when(unit_mode!=UNIT_MODE_DEFEND_TOWN);
  685. if(cur_action==SPRITE_ATTACK)
  686. return 1;
  687. if(town_array.is_deleted(unit_mode_para))
  688. {
  689. stop2(); //**** BUGHERE
  690. set_mode(0); //***BUGHERE
  691. return 0;
  692. }
  693. int curXLoc = next_x_loc();
  694. int curYLoc = next_y_loc();
  695. Town *townPtr = town_array[unit_mode_para];
  696. if((curXLoc<townPtr->center_x-UNIT_DEFEND_TOWN_DISTANCE) || (curXLoc>townPtr->center_x+UNIT_DEFEND_TOWN_DISTANCE) ||
  697. (curYLoc<townPtr->center_y-UNIT_DEFEND_TOWN_DISTANCE) || (curYLoc>townPtr->center_y+UNIT_DEFEND_TOWN_DISTANCE))
  698. {
  699. defend_town_back_town(unit_mode_para);
  700. return 0;
  701. }
  702. return 1;
  703. }
  704. //----------- End of function Unit::defend_town_follow_target -----------//
  705. //------------- Begin of function Unit::clear_town_defend_mode --------------//
  706. // clear defend mode
  707. //
  708. void Unit::clear_town_defend_mode()
  709. {
  710. //------- cancel defense mode and continue the current action -------//
  711. action_mode2 = action_mode;
  712. action_para2 = action_para;
  713. action_x_loc2 = action_x_loc;
  714. action_y_loc2 = action_y_loc;
  715. reset_action_misc_para();
  716. }
  717. //----------------- End of function Unit::clear_town_defend_mode ----------------//
  718. //=================================================================================================//
  719. // Monster unit's defend mode
  720. //=================================================================================================//
  721. //--------- Begin of function Unit::monster_defend_attack_unit ---------//
  722. // set to attack target
  723. //
  724. // <short> targetRecno - recno of the target
  725. //
  726. void Unit::monster_defend_attack_unit(short targetRecno)
  727. {
  728. action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET;
  729. attack_unit(targetRecno);
  730. }
  731. //----------- End of function Unit::monster_defend_attack_unit -----------//
  732. //--------- Begin of function Unit::monster_defend_attack_firm ---------//
  733. // set monster to attack firm
  734. //
  735. // <int> targetXLoc - x location of firm
  736. // <int> targetYLoc - y location of firm
  737. //
  738. void Unit::monster_defend_attack_firm(int targetXLoc, int targetYLoc)
  739. {
  740. action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET;
  741. attack_firm(targetXLoc, targetYLoc);
  742. }
  743. //----------- End of function Unit::monster_defend_attack_firm -----------//
  744. //--------- Begin of function Unit::monster_defend_attack_town ---------//
  745. // set monster to attack town
  746. //
  747. // <int> targetXLoc - x location of the town
  748. // <int> targetYLoc - y location of the town
  749. //
  750. void Unit::monster_defend_attack_town(int targetXLoc, int targetYLoc)
  751. {
  752. action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET;
  753. attack_town(targetXLoc, targetYLoc);
  754. }
  755. //----------- End of function Unit::monster_defend_attack_town -----------//
  756. //--------- Begin of function Unit::monster_defend_attack_wall ---------//
  757. // set monster to attack wall
  758. //
  759. // <int> targetXLoc - x location of wall
  760. // <int> targetYLoc - y location of wall
  761. //
  762. void Unit::monster_defend_attack_wall(int targetXLoc, int targetYLoc)
  763. {
  764. action_mode2 = ACTION_MONSTER_DEFEND_ATTACK_TARGET;
  765. attack_wall(targetXLoc, targetYLoc);
  766. }
  767. //----------- End of function Unit::monster_defend_attack_wall -----------//
  768. //--------- Begin of function Unit::monster_defend_detect_target ---------//
  769. // set to detect mode
  770. //
  771. void Unit::monster_defend_detect_target()
  772. {
  773. action_mode2 = ACTION_MONSTER_DEFEND_DETECT_TARGET;
  774. action_para2 = MONSTER_DEFEND_DETECT_COUNT;
  775. action_x_loc2 = -1;
  776. action_y_loc2 = -1;
  777. }
  778. //----------- End of function Unit::monster_defend_detect_target -----------//
  779. //--------- Begin of function Unit::monster_defend_back_firm ---------//
  780. // set to return mode
  781. //
  782. void Unit::monster_defend_back_firm(int firmXLoc, int firmYLoc)
  783. {
  784. err_when(firm_array[world.get_loc(firmXLoc, firmYLoc)->firm_recno()]->firm_id!=FIRM_MONSTER);
  785. assign(firmXLoc, firmYLoc);
  786. action_mode2 = ACTION_MONSTER_DEFEND_BACK_FIRM;
  787. }
  788. //----------- End of function Unit::monster_defend_back_firm -----------//
  789. //--------- Begin of function Unit::process_monster_defend_attack_target ---------//
  790. // proces attack mode
  791. //
  792. void Unit::process_monster_defend_attack_target()
  793. {
  794. err_when(action_mode2!=ACTION_MONSTER_DEFEND_ATTACK_TARGET);
  795. if(general_defend_mode_process_attack_target())
  796. {
  797. monster_defend_detect_target();
  798. err_when(action_mode!=ACTION_STOP || action_para || action_x_loc!=-1 || action_y_loc!=-1 || cur_action==SPRITE_ATTACK);
  799. }
  800. }
  801. //----------- End of function Unit::process_monster_defend_attack_target -----------//
  802. //--------- Begin of function Unit::process_monster_defend_detect_target ---------//
  803. // process detect mode
  804. //
  805. void Unit::process_monster_defend_detect_target()
  806. {
  807. err_when(action_mode2!=ACTION_MONSTER_DEFEND_DETECT_TARGET);
  808. err_when(action_mode!=ACTION_STOP);
  809. err_when(action_para!=0);
  810. err_when(action_x_loc!=-1 || action_y_loc!=-1 || action_x_loc!=-1 || action_y_loc2!=-1);
  811. //----------------------------------------------------------------//
  812. // no target or target is out of detect range, so change state to
  813. // back camp
  814. //----------------------------------------------------------------//
  815. if(!action_para2)
  816. {
  817. err_when(action_misc!=ACTION_MISC_MONSTER_DEFEND_FIRM_RECNO || !action_misc_para);
  818. err_when(unit_mode!=UNIT_MODE_MONSTER || !unit_mode_para);
  819. int back = 0;
  820. Unit *targetPtr;
  821. FirmMonster *firmMonsterPtr;
  822. if(firm_array.is_deleted(action_misc_para))
  823. back++;
  824. else
  825. {
  826. firmMonsterPtr = (FirmMonster*) firm_array[action_misc_para];
  827. if(unit_array.is_deleted(firmMonsterPtr->defend_target_recno))
  828. back++;
  829. else
  830. {
  831. targetPtr = unit_array[firmMonsterPtr->defend_target_recno];
  832. if(targetPtr->action_mode!=ACTION_ATTACK_FIRM || targetPtr->action_para!=firmMonsterPtr->firm_recno)
  833. back++;
  834. }
  835. }
  836. if(!back)
  837. {
  838. //action_mode2 = ACTION_MONSTER_DEFEND_DETECT_TARGET;
  839. action_para2 = MONSTER_DEFEND_DETECT_COUNT;
  840. return;
  841. }
  842. process_monster_defend_back_firm();
  843. return;
  844. }
  845. //----------------------------------------------------------------//
  846. // defense_detecting target algorithm
  847. //----------------------------------------------------------------//
  848. int startLoc;
  849. int dimension;
  850. switch(action_para2%GAME_FRAMES_PER_DAY)
  851. {
  852. case 3: startLoc = 2;// 1-7, check 224 = 15^2-1
  853. //### begin alex 3/10 ###//
  854. dimension = 7;
  855. //#### end alex 3/10 ####//
  856. break;
  857. case 2: startLoc = 122;// 6-8, check 168 = 17^2-11^2
  858. dimension = 8;
  859. break;
  860. case 1: startLoc = 170;// 7-9, check 192 = 19^2-13^2
  861. dimension = EFFECTIVE_MONSTER_DEFEND_FIRM_DISTANCE;
  862. break;
  863. default: action_para2--;
  864. return;
  865. }
  866. //---------------------------------------------------------------//
  867. // attack the target if target detected, or change the detect region
  868. //---------------------------------------------------------------//
  869. if(!idle_detect_attack(startLoc, dimension, 1)) // defense mode is on
  870. action_para2--;
  871. }
  872. //----------- End of function Unit::process_monster_defend_detect_target -----------//
  873. //--------- Begin of function Unit::process_monster_defend_back_firm ---------//
  874. // process return mode
  875. //
  876. void Unit::process_monster_defend_back_firm()
  877. {
  878. int clearDefendMode = 0;
  879. if(action_mode!=ACTION_ASSIGN_TO_FIRM) // the unit may become idle or unable to reach firm, reactivate it
  880. {
  881. Firm *firmPtr;
  882. if(action_misc!=ACTION_MISC_MONSTER_DEFEND_FIRM_RECNO || !action_misc_para || firm_array.is_deleted(action_misc_para))
  883. clearDefendMode++;
  884. else
  885. {
  886. firmPtr = firm_array[action_misc_para];
  887. if(firmPtr->firm_id!=FIRM_MONSTER || firmPtr->nation_recno!=nation_recno)
  888. clearDefendMode++;
  889. else
  890. {
  891. monster_defend_back_firm(firmPtr->loc_x1, firmPtr->loc_y1); // go back to the military camp
  892. err_when(action_mode2!=ACTION_MONSTER_DEFEND_BACK_FIRM);
  893. return;
  894. }
  895. }
  896. }
  897. else if(cur_action==SPRITE_IDLE)
  898. {
  899. if(firm_array.is_deleted(action_misc_para))
  900. clearDefendMode++;
  901. else
  902. {
  903. Firm *firmPtr = firm_array[action_misc_para];
  904. monster_defend_back_firm(firmPtr->loc_x1, firmPtr->loc_y1);
  905. err_when(action_mode2!=ACTION_MONSTER_DEFEND_BACK_FIRM);
  906. return;
  907. }
  908. }
  909. err_when(!clearDefendMode);
  910. //----------------------------------------------------------------//
  911. // clear order if the camp is deleted
  912. //----------------------------------------------------------------//
  913. stop2();
  914. reset_action_misc_para();
  915. err_when(in_monster_defend_mode());
  916. }
  917. //----------- End of function Unit::process_monster_defend_back_firm -----------//
  918. //------------- Begin of function Unit::in_monster_defend_mode --------------//
  919. // check whether the unit is in defend mode
  920. //
  921. int Unit::in_monster_defend_mode()
  922. {
  923. return (action_mode2>=ACTION_MONSTER_DEFEND_ATTACK_TARGET && action_mode2<=ACTION_MONSTER_DEFEND_BACK_FIRM);
  924. }
  925. //----------- End of function Unit::in_monster_defend_mode -----------//
  926. //------------- Begin of function Unit::monster_defend_follow_target --------------//
  927. // make decision to choose to follow target or return
  928. //
  929. // return 0 if aborting attack the current target and go back to military camp
  930. // return 1 otherwise
  931. //
  932. int Unit::monster_defend_follow_target()
  933. {
  934. //######## begin trevor 22/8 ##########//
  935. err_when( unit_mode!=UNIT_MODE_MONSTER || !unit_mode_para );
  936. if(cur_action==SPRITE_ATTACK)
  937. return 1;
  938. /*
  939. if(firm_array.is_deleted(action_misc_para))
  940. {
  941. stop2(); //**** BUGHERE
  942. //set_mode(0); //***BUGHERE
  943. if(monster_array.is_deleted(unit_mode_para))
  944. return 0;
  945. Monster *monsterPtr = monster_array[unit_mode_para];
  946. monsterPtr->firm_recno = 0;
  947. return 0;
  948. }
  949. */
  950. //######## end trevor 22/8 ##########//
  951. //--------------------------------------------------------------------------------//
  952. // choose to return to firm
  953. //--------------------------------------------------------------------------------//
  954. int curXLoc = next_x_loc();
  955. int curYLoc = next_y_loc();
  956. Firm *firmPtr = firm_array[action_misc_para];
  957. if((curXLoc<firmPtr->center_x-MONSTER_DEFEND_FIRM_DISTANCE) || (curXLoc>firmPtr->center_x+MONSTER_DEFEND_FIRM_DISTANCE) ||
  958. (curYLoc<firmPtr->center_y-MONSTER_DEFEND_FIRM_DISTANCE) || (curYLoc>firmPtr->center_y+MONSTER_DEFEND_FIRM_DISTANCE))
  959. {
  960. monster_defend_back_firm(firmPtr->loc_x1, firmPtr->loc_y1);
  961. return 0;
  962. }
  963. return 1;
  964. }
  965. //----------- End of function Unit::monster_defend_follow_target -----------//
  966. //------------- Begin of function Unit::clear_monster_defend_mode --------------//
  967. // clear defend mode
  968. //
  969. void Unit::clear_monster_defend_mode()
  970. {
  971. err_when(!in_monster_defend_mode());
  972. //------- cancel defense mode and continue the current action -------//
  973. action_mode2 = action_mode;
  974. action_para2 = action_para;
  975. action_x_loc2 = action_x_loc;
  976. action_y_loc2 = action_y_loc;
  977. reset_action_misc_para();
  978. }
  979. //----------------- End of function Unit::clear_monster_defend_mode ----------------//