source: golgotha/src/golg/objs/supergun.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 11 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 5.5 KB
Line 
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
9#include "sound_man.hh"
10#include "objs/model_id.hh"
11#include "objs/model_draw.hh"
12#include "objs/supergun.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 "sfx_id.hh"
23#include "object_definer.hh"
24#include "objs/target.hh"
25#include "lisp/lisp.hh"
26#include "objs/fire.hh"
27
28enum {DATA_VERSION=1};
29enum
30{
31  ACQUIRE,
32  TARGET,
33  FIRING,
34};
35 
36static li_symbol_ref super_mortar("super_mortar");
37
38g1_object_definer<g1_supergun_class>
39g1_supergun_def("supergun", g1_object_definition_class::EDITOR_SELECTABLE);
40
41
42
43
44void g1_supergun_class::setup(i4_float _x, i4_float _y, g1_object_class *creator)
45{
46  x = x;
47  y = y;
48  player_num = creator->player_num;
49  occupy_location();
50  request_think();
51  grab_old();
52}
53
54g1_supergun_class::g1_supergun_class(g1_object_type id,
55                                 g1_loader_class *fp)
56  : g1_map_piece_class(id,fp)
57
58  defaults = g1_supergun_def.defaults;
59  draw_params.setup("supergun_base");
60 
61  allocate_mini_objects(2,"supergun_barrel");
62  muzzle = &mini_objects[0];
63  muzzle->x = muzzle->lx = g1_resources.supergun_muzzle_attach.x;
64  muzzle->y = muzzle->ly = g1_resources.supergun_muzzle_attach.y;
65  muzzle->h = muzzle->lh = g1_resources.supergun_muzzle_attach.z;
66  muzzle->rotation.set(0,0,0);
67  muzzle->defmodeltype = g1_model_list_man.find_handle("supergun_barrel");
68  muzzle->grab_old();
69 
70  w16 ver,data_size;
71  if (fp)
72    fp->get_version(ver,data_size);
73  else
74    ver=0;
75
76  switch (ver)
77  {
78    case DATA_VERSION:
79      break;
80    default:
81      if (fp) fp->seek(fp->tell() + data_size);
82      health = defaults->health;
83      break;
84  }
85
86  fire_delay = 0;
87  time = 0;
88  mode = ACQUIRE;
89
90  radar_type=G1_RADAR_BUILDING;
91  set_flag(BLOCKING      |
92           SELECTABLE    |
93           GROUND        |
94           HIT_GROUND    |
95           DANGEROUS     |
96           SHADOWED, 1);
97}
98
99void g1_supergun_class::save(g1_saver_class *fp)
100{
101  g1_map_piece_class::save(fp);
102 
103  fp->start_version(DATA_VERSION);
104
105  fp->end_version();
106}
107
108i4_bool g1_supergun_class::suggest_new_attack_target(g1_object_class *new_target,
109                                                     g1_fire_range_type range)
110{
111  attack_target = new_target;
112  mode = ACQUIRE;
113  return i4_T;
114}
115
116
117void g1_supergun_class::fire()
118{
119  fire_delay = defaults->fire_delay;
120  muzzle->offset.x = -0.2;
121 
122  i4_3d_point_class bpos, bdir;
123  i4_transform_class btrans, tmp1, tmp2;
124 
125  tmp1.rotate_y(target_pitch);
126  tmp1.t.set(muzzle->x,muzzle->y,muzzle->h);
127
128  tmp2.rotate_z(target_angle);
129  tmp2.t.set(x,y,h);
130
131  btrans.multiply(tmp2,tmp1);
132
133  btrans.transform(i4_3d_point_class(1.5,0,0),bpos);
134
135  bdir.set(target_groundspeed*cos(theta), target_groundspeed*sin(theta), target_zspeed);
136  g1_fire(super_mortar.get(), this, 0,  bpos, bdir, 0);
137}
138
139i4_bool g1_supergun_class::deploy_to(float tx, float ty)
140{
141  i4_3d_vector d(tx, ty, g1_get_map()->terrain_height(tx,ty));
142
143  d -= i4_3d_vector(x,y,h);
144
145  //aim the turet
146  target_angle = i4_atan2(d.y,d.x);
147  i4_normalize_angle(target_angle);
148     
149  target_pitch = -(g1_float_rand(4)*i4_pi()/12.0 + i4_pi()/6);
150  i4_normalize_angle(target_pitch);
151
152  //                     --------------------
153  //  speed = d          |  -a
154  //         ------- * _ | -----------------
155  //         cos(th)    |/  2*(d*tan(th) - h)
156 
157  i4_float dist = sqrt(d.x*d.x + d.y*d.y) - 2.0;
158  i4_float den = (dist*tan(-target_pitch) - d.z)*2.0;
159
160  if (den>0 && dist>3.0)
161  {
162    target_groundspeed = dist*sqrt(g1_resources.gravity / den);
163    target_zspeed = target_groundspeed*tan(-target_pitch);
164    mode = TARGET;
165  }
166
167  return i4_T;
168}
169
170void g1_supergun_class::think()
171
172  if (!check_life()) 
173    return;
174
175  if (health>0 && health < defaults->health)
176    health+=200;
177
178  if (fire_delay>0)
179    fire_delay--;
180
181  pitch = 0;
182  roll  = 0;
183  h = terrain_height;
184
185  request_think();
186  switch(mode)
187  {
188    case ACQUIRE:
189    {
190      break;
191
192      i4_3d_vector d;
193
194#if 1
195      d.x = g1_float_rand(5)*g1_get_map()->width();
196      d.y = g1_float_rand(4)*g1_get_map()->height();
197#else
198      d.x = g1_get_map()->width()/2.0;
199      d.y = g1_get_map()->height()/2.0;
200#endif
201      if (attack_target.valid())
202      {
203        d.x = attack_target->x;
204        d.y = attack_target->y;
205      }
206
207      deploy_to(d.x,d.y);
208    } break;
209
210    case TARGET:
211    {
212      i4_bool aimed;
213
214      aimed = (i4_rotate_to(theta,target_angle,defaults->turn_speed)==0.0);
215      aimed = (i4_rotate_to(muzzle->rotation.y,target_pitch,defaults->turn_speed)==0.0) && aimed;
216      if (aimed)
217      {
218        mode = FIRING;
219        fire();
220      }
221    } break;
222
223    case FIRING:
224    {
225      if (muzzle->offset.x<0.0)
226      {
227        muzzle->offset.x += 0.01;
228        if (muzzle->offset.x>0.0) muzzle->offset.x=0.0;
229      }
230      if (fire_delay==0 && muzzle->offset.x==0.0)
231        mode = ACQUIRE;
232    } break;
233  }
234}
Note: See TracBrowser for help on using the repository browser.