helicopter.cc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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 "objs/bullet.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 "objs/vehic_sounds.hh"
  22. #include "sound/sfx_id.hh"
  23. #include "objs/helicopter.hh"
  24. #include "objs/fire.hh"
  25. #include "object_definer.hh"
  26. #include "objs/path_object.hh"
  27. #include "camera.hh"
  28. #include "image_man.hh"
  29. static g1_team_icon_ref radar_im("bitmaps/radar/helicopter.tga");
  30. static g1_model_ref model_ref("heli_body"),
  31. shadow_ref("heli_body_shadow"),
  32. blades_ref("heli_blades-alpha");
  33. static i4_3d_vector blades_attach, blades_offset;
  34. enum {DATA_VERSION=2};
  35. enum helicopter_mode
  36. {
  37. TAKE_OFF=0,
  38. TAKE_OFF2,
  39. FLYING,
  40. DYING
  41. };
  42. const i4_float fly_height = 1.5;
  43. const i4_float max_bladespeed = 0.75;
  44. static g1_object_type missile;
  45. void g1_helicopter_init()
  46. {
  47. missile = g1_get_object_type("guided_missile");
  48. blades_attach.set(0,0,0);
  49. model_ref()->get_mount_point("Blades", blades_attach);
  50. blades_offset.set(0,0,0);
  51. blades_ref()->get_mount_point("Blades", blades_offset);
  52. }
  53. g1_object_definer<g1_helicopter_class>
  54. g1_helicopter_def("helicopter",
  55. g1_object_definition_class::TO_MAP_PIECE |
  56. g1_object_definition_class::EDITOR_SELECTABLE |
  57. g1_object_definition_class::MOVABLE,
  58. g1_helicopter_init);
  59. g1_helicopter_class::g1_helicopter_class(g1_object_type id,
  60. g1_loader_class *fp)
  61. : g1_map_piece_class(id,fp)
  62. {
  63. radar_image=&radar_im;
  64. radar_type=G1_RADAR_VEHICLE;
  65. set_flag(BLOCKING |
  66. TARGETABLE |
  67. AERIAL |
  68. HIT_AERIAL |
  69. HIT_GROUND |
  70. DANGEROUS,
  71. 1);
  72. draw_params.setup("heli_body","heli_body_shadow");
  73. //allocate 1 mini object
  74. allocate_mini_objects(1,"Helicopter Mini-Objects");
  75. blades = &mini_objects[0];
  76. //setup blades
  77. blades->defmodeltype = blades_ref.id();
  78. blades->position(blades_attach);
  79. blades->offset = blades_offset;
  80. bladespeed = 0;
  81. w16 ver,data_size;
  82. if (fp)
  83. fp->get_version(ver,data_size);
  84. else
  85. ver =0;
  86. switch (ver)
  87. {
  88. case DATA_VERSION:
  89. mode = 0;
  90. fp->read_format("1ffffff",
  91. &mode,
  92. &blades->rotation.x,&blades->rotation.x,&blades->rotation.x,
  93. &bladespeed,
  94. &vspeed,
  95. &upaccel);
  96. grab_old();
  97. break;
  98. case 1:
  99. mode = 0;
  100. if (fp->read_8()) mode=TAKE_OFF; // take_off
  101. if (fp->read_8()) mode=TAKE_OFF; // taking_off
  102. if (fp->read_8()) mode=FLYING; // flying
  103. fp->read_8();
  104. fp->read_8();
  105. blades->rotation.x = fp->read_float();
  106. blades->rotation.y = fp->read_float();
  107. blades->rotation.z = fp->read_float();
  108. fp->read_float();
  109. fp->read_float();
  110. fp->read_float();
  111. bladespeed = fp->read_float();
  112. vspeed = fp->read_float();
  113. upaccel = fp->read_float();
  114. break;
  115. default:
  116. if (fp) fp->seek(fp->tell() + data_size);
  117. mode = TAKE_OFF;
  118. blades->rotation.x = blades->lrotation.x = 0;
  119. blades->rotation.y = blades->lrotation.y = 0;
  120. blades->rotation.z = blades->lrotation.z = 0;
  121. bladespeed = 0;
  122. vspeed = upaccel = 0;
  123. break;
  124. }
  125. if (fp)
  126. fp->end_version(I4_LF);
  127. fire_delay = 0;
  128. blades->defmodeltype = g1_model_list_man.find_handle("heli_blades-alpha");
  129. blades->lod_model = blades->defmodeltype;
  130. draw_params.setup("heli_body","heli_body_shadow", "heli_body_lod");
  131. init_rumble_sound(G1_RUMBLE_HELI);
  132. damping_fraction = 0.02;
  133. bladespeed=max_bladespeed;
  134. }
  135. static char *chunk_list[3]={"chunk_chopper_blade","chunk_chopper_body", "chunk_chopper_tail"};
  136. int g1_helicopter_class::get_chunk_names(char **&list) { list=chunk_list; return 3; }
  137. void g1_helicopter_class::save(g1_saver_class *fp)
  138. {
  139. g1_map_piece_class::save(fp);
  140. fp->start_version(DATA_VERSION);
  141. fp->write_format("1ffffff",
  142. &mode,
  143. &blades->rotation.x,&blades->rotation.x,&blades->rotation.x,
  144. &bladespeed,
  145. &vspeed,
  146. &upaccel);
  147. fp->end_version();
  148. }
  149. void g1_helicopter_class::fire()
  150. {
  151. g1_object_class *target=attack_target.get();
  152. if (target)
  153. {
  154. i4_transform_class btrans,tmp1;
  155. i4_3d_vector pos1, pos2, dir;
  156. btrans.translate(x,y,h);
  157. tmp1.rotate_x(groundroll);
  158. btrans.multiply(tmp1);
  159. tmp1.rotate_y(groundpitch);
  160. btrans.multiply(tmp1);
  161. tmp1.rotate_z(theta);
  162. btrans.multiply(tmp1);
  163. tmp1.rotate_y(pitch);
  164. btrans.multiply(tmp1);
  165. tmp1.rotate_x(roll);
  166. btrans.multiply(tmp1);
  167. btrans.transform(i4_3d_vector(0.2, -0.11, -0.02), pos1);
  168. btrans.transform(i4_3d_vector(0.2, 0.11, -0.02), pos2);
  169. btrans.transform(i4_3d_vector(0.4, -0.11, -0.02), dir);
  170. dir-=pos1;
  171. g1_fire(defaults->fire_type, this, attack_target.get(), pos1, dir);
  172. g1_fire(defaults->fire_type, this, attack_target.get(), pos2, dir);
  173. fire_delay = defaults->fire_delay;
  174. }
  175. }
  176. i4_bool g1_helicopter_class::move(i4_float x_amount, i4_float y_amount)
  177. {
  178. unoccupy_location();
  179. x+=x_amount;
  180. y+=y_amount;
  181. g1_add_to_sound_average(rumble_type, i4_3d_vector(x,y,h));
  182. if (occupy_location())
  183. return i4_T;
  184. return i4_F;
  185. }
  186. void g1_helicopter_class::think()
  187. {
  188. if (!check_life(i4_F))
  189. mode = DYING;
  190. //physics
  191. blades->rotation.z -= bladespeed;
  192. h += vspeed;
  193. if (fire_delay>0) fire_delay--;
  194. switch (mode)
  195. {
  196. case TAKE_OFF:
  197. {
  198. g1_camera_event cev;
  199. cev.type=G1_WATCH_EVENT;
  200. cev.follow_object=this;
  201. g1_current_view_state()->suggest_camera_event(cev);
  202. mode=TAKE_OFF2;
  203. } break;
  204. case TAKE_OFF2:
  205. {
  206. if (next_path.valid())
  207. {
  208. dest_x = next_path->x - path_cos*path_len;
  209. dest_y = next_path->y - path_sin*path_len;
  210. dest_z = next_path->h - path_tan_phi*path_len;
  211. }
  212. //then raise the helicopter
  213. i4_float dist_to_go = dest_z - h;
  214. if (dist_to_go>0.05)
  215. {
  216. //if he is more than halfway away, accelerate down
  217. //otherwise accelerate up
  218. if (dist_to_go > (fly_height * 0.5))
  219. vspeed = (vspeed<0.05) ? vspeed+0.005 : vspeed;
  220. }
  221. else
  222. {
  223. //lock these there were any small errors
  224. h = dest_z;
  225. vspeed = 0;
  226. upaccel = 0;
  227. //think one more time so the l* variables catch up
  228. //(otherwise he'll bob up and down)
  229. if (h == lh)
  230. mode = FLYING;
  231. }
  232. }
  233. case FLYING:
  234. {
  235. find_target();
  236. if (next_path.valid())
  237. {
  238. dest_x = next_path->x;
  239. dest_y = next_path->y;
  240. dest_z = next_path->h;
  241. }
  242. i4_float dist, dtheta;
  243. i4_3d_vector d;
  244. suggest_air_move(dist, dtheta, d);
  245. move(d.x,d.y);
  246. h += d.z;
  247. if (dist<speed)
  248. advance_path();
  249. i4_float roll_to = -i4_pi()/4 * dtheta;
  250. i4_normalize_angle(roll_to);
  251. if (roll_to)
  252. i4_rotate_to(roll,roll_to,defaults->turn_speed/4);
  253. else
  254. i4_rotate_to(roll,0,defaults->turn_speed/2);
  255. if (attack_target.valid() && !fire_delay)
  256. fire();
  257. groundpitch = 0; //no ground when in the air (duh)
  258. groundroll = 0;
  259. } break;
  260. case DYING:
  261. {
  262. i4_float &roll_speed = dest_x;
  263. i4_float &theta_speed = dest_y;
  264. theta_speed += 0.02;
  265. theta += theta_speed;
  266. roll_speed += 0.02;
  267. roll += roll_speed;
  268. vspeed -= (g1_resources.gravity * 0.15);
  269. if (h<=terrain_height)
  270. g1_map_piece_class::damage(0,health,i4_3d_vector(0,0,1)); // die somehow!!!
  271. } break;
  272. }
  273. request_think();
  274. }
  275. void g1_helicopter_class::damage(g1_object_class *obj, int hp, i4_3d_vector _damage_dir)
  276. {
  277. //we dont want to explode if ppl shoot us while we're dying.. we want to
  278. //smash into the ground and create a nice explosion
  279. if (mode != DYING)
  280. {
  281. g1_map_piece_class::damage(obj,hp,_damage_dir);
  282. if (health<20)
  283. {
  284. i4_float &roll_speed = dest_x;
  285. i4_float &theta_speed = dest_y;
  286. roll_speed = 0;
  287. theta_speed = 0;
  288. health = 20;
  289. set_flag(DANGEROUS,0);
  290. mode = DYING;
  291. }
  292. }
  293. }