popup_turret.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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 "objs/popup_turret.hh"
  12. #include "input.hh"
  13. #include "math/pi.hh"
  14. #include "math/angle.hh"
  15. #include "math/trig.hh"
  16. #include "g1_rand.hh"
  17. #include "resources.hh"
  18. #include "saver.hh"
  19. #include "map_cell.hh"
  20. #include "map.hh"
  21. #include "map_man.hh"
  22. #include "object_definer.hh"
  23. #include "lisp/lisp.hh"
  24. #include "objs/fire.hh"
  25. enum {DATA_VERSION=1};
  26. static g1_model_ref model_ref("popup_housing"),
  27. mount_ref("popup_mount"),
  28. barrel_ref("popup_barrel");
  29. static g1_object_type bullet;
  30. static i4_3d_vector turret_attach, mount_offset, barrel_offset;
  31. //tunable variables
  32. // burst of fire.
  33. // rates of turning on, tracking
  34. // angle ranges
  35. // (weapons? maybe different objects)
  36. // entry range to fire
  37. const i4_float POPUP_HEIGHT = 0.4;
  38. const i4_float POPUP_SPEED = 0.1;
  39. const i4_float POPDOWN_SPEED = 0.05;
  40. const i4_float POPUP_ROTATESPEED = 0.3;
  41. void g1_popup_turret_init()
  42. {
  43. bullet = g1_get_object_type("bullet");
  44. turret_attach.set(0,0,0);
  45. model_ref()->get_mount_point("Mount Point", turret_attach);
  46. mount_offset.set(0,0,0.15);
  47. mount_ref()->get_mount_point("Mount Point", mount_offset);
  48. mount_offset.reverse();
  49. barrel_offset.set(0,0,0.15);
  50. barrel_ref()->get_mount_point("Mount Point", barrel_offset);
  51. barrel_offset.reverse();
  52. }
  53. g1_object_definer<g1_popup_turret_class>
  54. g1_popup_turret_def("popup_turret", g1_object_definition_class::EDITOR_SELECTABLE,
  55. g1_popup_turret_init);
  56. void g1_popup_turret_class::setup(i4_float _x, i4_float _y, g1_object_class *creator)
  57. {
  58. x = x;
  59. y = y;
  60. player_num = creator->player_num;
  61. occupy_location();
  62. request_think();
  63. grab_old();
  64. }
  65. g1_popup_turret_class::g1_popup_turret_class(g1_object_type id,
  66. g1_loader_class *fp)
  67. : g1_map_piece_class(id,fp)
  68. {
  69. radar_type=G1_RADAR_BUILDING;
  70. set_flag(BLOCKING |
  71. SELECTABLE |
  72. TARGETABLE |
  73. GROUND |
  74. HIT_GROUND |
  75. HIT_AERIAL |
  76. DANGEROUS |
  77. SHADOWED, 1);
  78. defaults = g1_popup_turret_def.defaults;
  79. draw_params.setup(model_ref.id());
  80. allocate_mini_objects(2,"popup_turret mini objects");
  81. mount = &mini_objects[0];
  82. mount->defmodeltype = mount_ref.id();
  83. mount->position(turret_attach);
  84. mount->rotation.set(0,0,0);
  85. mount->offset = mount_offset;
  86. barrel = &mini_objects[1];
  87. barrel->defmodeltype = barrel_ref.id();
  88. barrel->position(turret_attach);
  89. barrel->rotation.set(0,i4_pi()/2,0);
  90. barrel->offset = barrel_offset;
  91. if (fp && fp->check_version(DATA_VERSION))
  92. {
  93. fp->read_format("f",
  94. &mount->rotation.y);
  95. barrel->rotation.y = mount->rotation.y;
  96. fp->end_version(I4_LF);
  97. }
  98. else
  99. {
  100. health = defaults->health;
  101. }
  102. mount->grab_old();
  103. barrel->grab_old();
  104. }
  105. void g1_popup_turret_class::save(g1_saver_class *fp)
  106. {
  107. g1_map_piece_class::save(fp);
  108. fp->start_version(DATA_VERSION);
  109. fp->write_format("f",
  110. &mount->rotation.y);
  111. fp->end_version();
  112. }
  113. void g1_popup_turret_class::fire()
  114. {
  115. fire_delay = defaults->fire_delay;
  116. i4_3d_point_class tpos, bpos, bvel;
  117. i4_transform_class t, main, l2w;
  118. barrel->calc_transform(1.0, &t);
  119. calc_world_transform(1.0, &main);
  120. l2w.multiply(main, t);
  121. main.transform(turret_attach, bpos);
  122. l2w.transform_3x3(i4_3d_point_class(1.0, 0, 0), bvel);
  123. // spin the barrel
  124. barrel->rotation.x += 0.7;
  125. i4_normalize_angle(barrel->rotation.x);
  126. g1_fire(defaults->fire_type, this, attack_target.get(), bpos, bvel);
  127. }
  128. void g1_popup_turret_class::think()
  129. {
  130. find_target();
  131. if (health < defaults->health)
  132. health++;
  133. if (fire_delay>0)
  134. fire_delay--;
  135. //aim the turet
  136. if (attack_target.valid())
  137. {
  138. request_think();
  139. if (h < terrain_height+POPUP_HEIGHT-0.001)
  140. {
  141. h += POPUP_SPEED;
  142. if (h>terrain_height+POPUP_HEIGHT)
  143. h = terrain_height+POPUP_HEIGHT;
  144. }
  145. else
  146. {
  147. i4_3d_point_class d,pos;
  148. lead_target(d);
  149. pos.set(x,y,h-POPUP_HEIGHT);
  150. d -= pos;
  151. //aim the turet
  152. i4_float fire_angle,fire_pitch;
  153. fire_angle = i4_atan2(d.y,d.x);
  154. fire_pitch = i4_atan2(-d.z,sqrt(d.x*d.x+d.y*d.y));
  155. i4_normalize_angle(fire_angle);
  156. i4_normalize_angle(fire_pitch);
  157. int aimed=i4_F;
  158. i4_float dangle;
  159. dangle = i4_rotate_to(theta,fire_angle,defaults->turn_speed);
  160. aimed = (dangle<defaults->turn_speed && dangle>-defaults->turn_speed);
  161. dangle = i4_rotate_to(mount->rotation.y,fire_pitch,POPUP_ROTATESPEED);
  162. aimed &= (dangle<POPUP_ROTATESPEED && dangle>-POPUP_ROTATESPEED);
  163. barrel->rotation.y = mount->rotation.y;
  164. if (aimed)
  165. if (!fire_delay)
  166. fire();
  167. }
  168. }
  169. else
  170. {
  171. request_think(); // move this to draw function
  172. int aimed = i4_rotate_to(mount->rotation.y, i4_pi()/2, POPUP_ROTATESPEED)==0.0;
  173. barrel->rotation.y = mount->rotation.y;
  174. if (aimed && h>terrain_height)
  175. {
  176. h -= POPDOWN_SPEED;
  177. if (h<terrain_height)
  178. h = terrain_height;
  179. }
  180. }
  181. }