bomber.cc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /********************************************************************** <BR>
  2. This file is part of Crack dot Com's free source code release of
  3. Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
  4. information about compiling & licensing issues visit this URL</a>
  5. <PRE> If that doesn't help, contact Jonathan Clark at
  6. golgotha_source@usa.net (Subject should have "GOLG" in it)
  7. ***********************************************************************/
  8. #include "sound_man.hh"
  9. #include "objs/model_id.hh"
  10. #include "objs/model_draw.hh"
  11. #include "input.hh"
  12. #include "math/pi.hh"
  13. #include "math/trig.hh"
  14. #include "math/angle.hh"
  15. #include "g1_rand.hh"
  16. #include "resources.hh"
  17. #include "saver.hh"
  18. #include "map_cell.hh"
  19. #include "map.hh"
  20. #include "map_man.hh"
  21. #include "sfx_id.hh"
  22. #include "objs/bomber.hh"
  23. #include "objs/fire.hh"
  24. #include "object_definer.hh"
  25. #include "objs/path_object.hh"
  26. #include "image_man.hh"
  27. static g1_team_icon_ref radar_im("bitmaps/radar/plane.tga");
  28. enum { DATA_VERSION=1 };
  29. enum
  30. {
  31. TAKE_OFF=0,
  32. FLYING,
  33. DYING
  34. };
  35. const i4_float FLY_HEIGHT=1.5;
  36. void g1_bomber_init()
  37. //{{{
  38. {
  39. }
  40. //}}}
  41. g1_object_definer<g1_bomber_class>
  42. g1_bomber_def("bomber",
  43. g1_object_definition_class::TO_MAP_PIECE |
  44. g1_object_definition_class::EDITOR_SELECTABLE |
  45. g1_object_definition_class::MOVABLE,
  46. g1_bomber_init);
  47. g1_bomber_class::g1_bomber_class(g1_object_type id,
  48. g1_loader_class *fp)
  49. : g1_map_piece_class(id, fp)
  50. //{{{
  51. {
  52. draw_params.setup("bomber","bomber_shadow", "bomber_lod");
  53. damping_fraction = 0.02;
  54. radar_type=G1_RADAR_VEHICLE;
  55. radar_image=&radar_im;
  56. set_flag(BLOCKING |
  57. TARGETABLE |
  58. AERIAL |
  59. HIT_GROUND |
  60. DANGEROUS,1);
  61. w16 ver,data_size;
  62. if (fp)
  63. fp->get_version(ver,data_size);
  64. else
  65. ver =0;
  66. switch (ver)
  67. {
  68. case DATA_VERSION:
  69. fp->read_format("1f4",
  70. &mode,
  71. &vspeed,
  72. &sway);
  73. break;
  74. default:
  75. if (fp) fp->seek(fp->tell() + data_size);
  76. mode = 0;
  77. vspeed = 0;
  78. sway = 0;
  79. break;
  80. }
  81. if (fp)
  82. fp->end_version(I4_LF);
  83. }
  84. //}}}
  85. void g1_bomber_class::save(g1_saver_class *fp)
  86. //{{{
  87. {
  88. g1_map_piece_class::save(fp);
  89. fp->start_version(DATA_VERSION);
  90. fp->write_format("1f4",
  91. &mode,
  92. &vspeed,
  93. &sway);
  94. fp->end_version();
  95. }
  96. //}}}
  97. void g1_bomber_class::fire()
  98. //{{{
  99. {
  100. fire_delay = g1_bomber_def.defaults->fire_delay;
  101. i4_3d_vector pos(x,y,h);
  102. pos.x += g1_float_rand(3)*0.4-0.2;
  103. pos.y += g1_float_rand(2)*0.4-0.2;
  104. g1_fire(defaults->fire_type,
  105. this, attack_target.get(), pos,
  106. i4_3d_vector(x-lx,y-ly,h-lh));
  107. }
  108. //}}}
  109. i4_bool g1_bomber_class::move(i4_float x_amount, i4_float y_amount)
  110. //{{{
  111. {
  112. i4_float
  113. newx = x+x_amount,
  114. newy = y+y_amount;
  115. unoccupy_location();
  116. if (newx>0 && newx<g1_get_map()->width() && newy>0 && newy<g1_get_map()->height())
  117. {
  118. x = newx;
  119. y = newy;
  120. if (occupy_location())
  121. return i4_T;
  122. }
  123. request_remove();
  124. return i4_F;
  125. }
  126. //}}}
  127. void g1_bomber_class::think()
  128. //{{{
  129. {
  130. if (!check_life())
  131. return;
  132. find_target();
  133. if (fire_delay>0)
  134. fire_delay--;
  135. h += vspeed;
  136. switch (mode)
  137. {
  138. case TAKE_OFF:
  139. {
  140. if (next_path.valid())
  141. {
  142. dest_x = next_path->x - path_cos*path_len;
  143. dest_y = next_path->y - path_sin*path_len;
  144. dest_z = next_path->h - path_tan_phi*path_len;
  145. }
  146. //then raise the bomber
  147. i4_float dist_to_go = dest_z - h;
  148. if (dist_to_go>0.05)
  149. {
  150. //if he is more than halfway away, accelerate down
  151. //otherwise accelerate up
  152. if (dist_to_go > (FLY_HEIGHT * 0.5))
  153. vspeed = (vspeed<0.05) ? vspeed+0.005 : vspeed;
  154. }
  155. else
  156. {
  157. //lock these in case there were any small errors
  158. h = dest_z;
  159. vspeed = 0;
  160. //think one more time so the l* variables catch up
  161. //(otherwise he'll bob up and down)
  162. if (h == lh)
  163. mode = FLYING;
  164. }
  165. } break;
  166. case FLYING:
  167. {
  168. i4_3d_vector d;
  169. i4_float angle,t;
  170. // sway over terrain
  171. sway++;
  172. if (attack_target.valid())
  173. if (fire_delay==0)
  174. fire();
  175. i4_float roll_to = 0.02*sin(i4_pi()*sway/17.0);
  176. i4_float pitch_to = 0.02*sin(i4_pi()*sway/13.0);
  177. if (next_path.valid())
  178. {
  179. dest_x = next_path->x;
  180. dest_y = next_path->y;
  181. dest_z = next_path->h;
  182. }
  183. i4_float dist, dtheta;
  184. suggest_air_move(dist, dtheta, d);
  185. move(d.x,d.y);
  186. h += d.z + 0.02*sin(i4_pi()*sway/15.0);
  187. if (dist<speed)
  188. advance_path();
  189. i4_normalize_angle(roll_to);
  190. if (speed>0.001 || dtheta!=0.0)
  191. {
  192. roll_to = -i4_pi()/4 * dtheta;
  193. pitch_to = -i4_pi()/8 * speed;
  194. }
  195. i4_rotate_to(roll,roll_to,defaults->turn_speed/4);
  196. i4_rotate_to(pitch,pitch_to,defaults->turn_speed/4);
  197. groundpitch = 0; //no ground in the air (duh)
  198. groundroll = 0;
  199. } break;
  200. case DYING:
  201. {
  202. i4_float &roll_speed = dest_x;
  203. i4_float &pitch_speed = dest_y;
  204. pitch_speed += 0.004;
  205. pitch += pitch_speed;
  206. roll_speed += 0.01;
  207. roll += roll_speed;
  208. vspeed -= (g1_resources.gravity * 0.1);
  209. i4_float dx,dy;
  210. dx = speed*cos(theta);
  211. dy = speed*sin(theta);
  212. move(dx,dy);
  213. if (h<=terrain_height)
  214. g1_map_piece_class::damage(0,health,i4_3d_vector(0,0,1)); // die somehow!!!
  215. } break;
  216. }
  217. // have to keep thinking to sway
  218. request_think();
  219. }
  220. //}}}
  221. void g1_bomber_class::damage(g1_object_class *obj, int hp, i4_3d_vector _damage_dir)
  222. //{{{
  223. {
  224. //we dont want to explode if ppl shoot us while we're dying.. we want to
  225. //smash into the ground and create a nice explosion
  226. if (mode != DYING)
  227. {
  228. if (health<20)
  229. {
  230. i4_float &roll_speed = dest_x;
  231. i4_float &pitch_speed = dest_y;
  232. roll_speed = 0;
  233. pitch_speed = 0;
  234. health = 20;
  235. set_flag(DANGEROUS,0);
  236. mode = DYING;
  237. }
  238. g1_map_piece_class::damage(obj,hp,_damage_dir);
  239. }
  240. }
  241. //}}}
  242. //{{{ Emacs Locals
  243. // Local Variables:
  244. // folded-file: t
  245. // End:
  246. //}}}