OB_HOMIN.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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 : OB_HOMIN.H
  21. // Description : BulletHoming, Homing bullet
  22. #include <OB_HOMIN.h>
  23. #include <OWORLD.h>
  24. // --------- define constant --------//
  25. enum
  26. {
  27. BULLET_TARGET_NONE =0,
  28. BULLET_TARGET_UNIT =1,
  29. BULLET_TARGET_TOWN,
  30. BULLET_TARGET_FIRM,
  31. BULLET_TARGET_WALL,
  32. };
  33. // --------- begin of function BulletHoming::BulletHoming --------//
  34. BulletHoming::BulletHoming() : Bullet()
  35. {
  36. target_type = BULLET_TARGET_NONE;
  37. target_recno = 0;
  38. }
  39. // --------- end of function BulletHoming::BulletHoming --------//
  40. // --------- begin of function BulletHoming::~BulletHoming --------//
  41. BulletHoming::~BulletHoming()
  42. {
  43. deinit();
  44. }
  45. // --------- end of function BulletHoming::BulletHoming --------//
  46. // --------- begin of function BulletHoming::init --------//
  47. void BulletHoming::init(char parentType, short parentRecno, short targetXLoc, short targetYLoc, char targetMobileType)
  48. {
  49. Bullet::init(parentType, parentRecno, targetXLoc, targetYLoc, targetMobileType);
  50. // ------- find the maximum range --------//
  51. //**** BUGHERE, using parentType and parentRecno to allow bullet by firm, town, etc.
  52. //**** BUGHERE, only allow bullet by unit for this version
  53. err_when(parent_type!=BULLET_BY_UNIT);
  54. Unit *parentUnit = unit_array[parentRecno];
  55. //---------- copy attack info from the parent unit --------//
  56. AttackInfo* attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack;
  57. speed = attackInfo->bullet_speed;
  58. max_step = char((attackInfo->attack_range * ZOOM_LOC_WIDTH + speed-1)/ speed);
  59. //--------- keep backup of centre of the bullet ---------//
  60. SpriteFrame *spriteFrame = cur_sprite_frame();
  61. // origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap //
  62. origin_x += spriteFrame->offset_x + spriteFrame->width/2;
  63. origin_y += spriteFrame->offset_y + spriteFrame->height/2;
  64. origin2_x = origin_x;
  65. origin2_y = origin_y;
  66. go_x += spriteFrame->offset_x + spriteFrame->width/2;
  67. go_y += spriteFrame->offset_y + spriteFrame->height/2;
  68. // ------- find the target_type and target_recno ------//
  69. Location *locPtr = world.get_loc(targetXLoc, targetYLoc);
  70. //### begin alex 16/5 ###//
  71. //if( locPtr->has_unit(mobile_type) )
  72. if(locPtr->has_unit(targetMobileType))
  73. {
  74. target_type = BULLET_TARGET_UNIT;
  75. //target_recno = locPtr->unit_recno(mobile_type);
  76. target_recno = locPtr->unit_recno(targetMobileType);
  77. }
  78. //#### end alex 16/5 ####//
  79. else if( locPtr->is_town() )
  80. {
  81. target_type = BULLET_TARGET_TOWN;
  82. target_recno = locPtr->town_recno();
  83. }
  84. else if( locPtr->is_firm() )
  85. {
  86. target_type = BULLET_TARGET_FIRM;
  87. target_recno = locPtr->firm_recno();
  88. }
  89. else if( locPtr->is_wall() )
  90. {
  91. target_type = BULLET_TARGET_WALL;
  92. }
  93. }
  94. // --------- end of function BulletHoming::init --------//
  95. // --------- begin of function BulletHoming::deinit --------//
  96. void BulletHoming::deinit()
  97. {
  98. }
  99. // --------- end of function BulletHoming::deinit --------//
  100. // --------- begin of function BulletHoming::process_move --------//
  101. void BulletHoming::process_move()
  102. {
  103. int actualStep = total_step;
  104. if(target_type == BULLET_TARGET_UNIT)
  105. {
  106. Unit *unitPtr;
  107. if( unit_array.is_deleted(target_recno) ||
  108. !(unitPtr = unit_array[target_recno]) ||
  109. !unitPtr->is_visible() )
  110. {
  111. // target lost/die, proceed to Bullet::process_move
  112. target_type = BULLET_TARGET_NONE;
  113. }
  114. else
  115. {
  116. // ---- calculate new target_x_loc, target_y_loc -----//
  117. target_x_loc = unitPtr->next_x_loc();
  118. target_y_loc = unitPtr->next_y_loc();
  119. // ---- re-calculate go_x, go_y ------//
  120. // go_x/y and origin2_x/y are pointing at the centre of the bullet bitmap
  121. // it is different from Bullet
  122. go_x = unitPtr->cur_x + ZOOM_LOC_WIDTH / 2;
  123. go_y = unitPtr->cur_y + ZOOM_LOC_HEIGHT /2;
  124. //---------- set bullet movement steps -----------//
  125. SpriteFrame *spriteFrame = cur_sprite_frame();
  126. int adjX = spriteFrame->offset_x+spriteFrame->width/2;
  127. int adjY = spriteFrame->offset_y+spriteFrame->height/2;
  128. int xStep = abs(go_x - (cur_x+adjX))/speed;
  129. int yStep = abs(go_y - (cur_y+adjY))/speed;
  130. total_step = cur_step + max(xStep, yStep);
  131. // a homing bullet has a limited range, if the target go outside the
  132. // the limit, the bullet can't attack the target
  133. // in this case, actualStep is the number step from the source
  134. // to the target; total_step is the max_step
  135. // otherwise, actualStep is as same as total_step
  136. actualStep = total_step;
  137. if( total_step > max_step )
  138. {
  139. total_step = max_step;
  140. // target_x_loc and target_y_loc is limited also
  141. target_x_loc = (cur_x + adjX) + (int)(go_x-(cur_x+adjX)) / (actualStep - total_step) / ZOOM_LOC_WIDTH;
  142. target_x_loc = (cur_y + adjY) + (int)(go_y-(cur_y+adjY)) / (actualStep - total_step) / ZOOM_LOC_HEIGHT;
  143. }
  144. }
  145. }
  146. // origin2_x = origin_x;
  147. // origin2_y = origin_y;
  148. // origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap //
  149. SpriteFrame *spriteFrame = cur_sprite_frame();
  150. short adjX = spriteFrame->offset_x + spriteFrame->width/2;
  151. short adjY = spriteFrame->offset_y + spriteFrame->height/2;
  152. origin_x = cur_x + adjX;
  153. origin_y = cur_y + adjY;
  154. cur_x = origin_x + (int)(go_x-origin_x) / (actualStep + 1 - cur_step);
  155. cur_y = origin_y + (int)(go_y-origin_y) / (actualStep + 1 - cur_step);
  156. // cur_x, cur_y is temporary pointing at the centre of bullet bitmap
  157. // detect changing direction
  158. if( cur_step > 3 ) // not allow changing direction so fast
  159. set_dir(origin2_x, origin2_y, cur_x, cur_y);
  160. // change cur_x, cur_y to bitmap reference point
  161. spriteFrame= cur_sprite_frame();
  162. adjX = spriteFrame->offset_x + spriteFrame->width/2;
  163. adjY = spriteFrame->offset_y + spriteFrame->height/2;
  164. cur_x -= adjX;
  165. cur_y -= adjY;
  166. cur_step++;
  167. //------- update frame id. --------//
  168. if( ++cur_frame > cur_sprite_move()->frame_count )
  169. cur_frame = 1;
  170. //----- if the sprite has reach the destintion ----//
  171. if( cur_step > total_step )
  172. {
  173. check_hit();
  174. cur_action = SPRITE_DIE; // Explosion
  175. // ###### begin Gilbert 17/5 ########//
  176. // if it has die frame, adjust cur_x, cur_y to be align with the target_x_loc, target_y_loc
  177. if( sprite_info->die.first_frame_recno )
  178. {
  179. next_x = cur_x = target_x_loc * ZOOM_LOC_WIDTH;
  180. next_y = cur_y = target_y_loc * ZOOM_LOC_HEIGHT;
  181. }
  182. // ###### end Gilbert 17/5 ########//
  183. cur_frame = 1;
  184. }
  185. // change of total_step may not call warn_target, so call more warn_target
  186. else if( total_step - cur_step <= 1 )
  187. {
  188. warn_target();
  189. }
  190. }
  191. // --------- end of function BulletHoming::process_move --------//