source: golgotha/src/golg/objs/guided_missile.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: 8.7 KB
RevLine 
[80]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 "g1_object.hh"
10#include "tile.hh"
11#include "math/num_type.hh"
12#include "math/pi.hh"
13#include "math/trig.hh"
14#include "math/angle.hh"
15#include "g1_rand.hh"
16#include "objs/model_draw.hh"
17#include "objs/explosion1.hh"
18#include "objs/map_piece.hh"
19#include "saver.hh"
20#include "map.hh"
21#include "map_man.hh"
22#include "object_definer.hh"
23#include "resources.hh"
24#include "player.hh"
25#include "objs/particle_emitter.hh"
26#include "g1_render.hh"
27#include "flare.hh"
28#include "objs/guided_missile.hh"
29#include "sound/sfx_id.hh"
30#include "lisp/lisp.hh"
31#include "li_objref.hh"
32#include "lisp/li_vect.hh"
33#include "objs/smoke_trail.hh"
34#include "objs/vehic_sounds.hh"
35#include "camera.hh"
36#include "time/profile.hh"
37
38static i4_profile_class pf_missile("missile_think");
39
40g1_object_definer<g1_guided_missile_class>
41g1_guided_missile_def("guided_missile");
42
43static li_symbol_ref li_smoke_trail("smoke_trail");
44static li_symbol_ref li_explosion1("explosion1");
45static li_g1_ref_class_member track_object("track_object");
46static li_g1_ref_class_member smoke_trail("smoke_trail");
47static li_g1_ref_class_member who_fired_me("who_fired_me");
48static li_vect_class_member velocity("velocity");
49static li_float_class_member fuel("fuel");
50
51static li_symbol_ref light_type("lightbulb");
52
53g1_guided_missile_class::g1_guided_missile_class(g1_object_type id,
54                                                 g1_loader_class *fp)
55  : g1_object_class(id,fp)
56{     
57  radar_type=G1_RADAR_WEAPON;
58
59  char lod_name[256];
60  draw_params.setup(name());
61  set_flag(AERIAL        |
62           HIT_AERIAL    |
63           HIT_GROUND    |
64           SHADOWED,
65           1);
66
67  damping_fraction = 1.0 - get_type()->defaults->accel/get_type()->defaults->speed;
68}
69
70void g1_guided_missile_class::request_remove()
71{
72  li_class_context context(vars);
73
74  delete_smoke();
75
76  if (light.get())
77  {
78    light->unoccupy_location();
79    light->request_remove();
80  }
81
82 
83  g1_object_class::request_remove();
84}
85
86void g1_guided_missile_class::think()
87{   
88  pf_missile.start();
89  i4_3d_vector accel;
90  i4_3d_vector vel=velocity();
91
92  if (fuel() > 0)
93  {
94    g1_object_class *track = track_object()->value();
95   
96    if (track)
97    {
98      i4_3d_vector pos(x,y,h);
99      i4_3d_vector lead(track->x, track->y, track->h + 0.05);
100      i4_3d_vector mp_diff(track->x - track->lx, track->y - track->ly, track->h - track->lh);
101      i4_3d_vector tvel(vel);
102
103      // leading code
104      i4_3d_vector diff(lead);
105      diff -= pos;
106
107      i4_float t = diff.length()/get_type()->defaults->speed;
108
109      mp_diff*=t;
110      lead += mp_diff;
111
112      // base acceleration vector
113      accel = lead;
114      accel -= pos;
115//       accel.z *= 1.5;             // correct height faster
116
117      // determine look ahead for ground avoidance
118      int look_ahead = i4_f_to_i(accel.length());
119      if (look_ahead>3) look_ahead=3;
120      accel.normalize();
121
122#if 0
123      // attempt to cancel old velocity
124      tvel.normalize();
125      tvel *= 0.4;
126      accel -= tvel;
127      accel.normalize();
128#endif
129
130#if 1
131      // attempt to cancel perp component of old velocity
132      if (vel.dot(accel)>0)
133      {
134        i4_3d_vector perp(-accel.y, accel.x, 0);
135
136        i4_float perp_vel = vel.dot(perp);
137
138        perp_vel /= get_type()->defaults->accel;
139        if (perp_vel<-1.0)
140          accel = perp;
141        else if (perp_vel>1.0)
142        {
143          accel = perp;
144          accel.reverse();
145        }
146        else
147        {
148          accel *= sqrt(1.0 - perp_vel*perp_vel);
149          perp *= -perp_vel;
150          accel += perp;
151        }
152      }
153#endif
154
155      if (accel.z>-0.5)
156      {
157        // ground tracking
158        i4_3d_vector p(pos);
159        i4_float height;
160        for (int i=0; i<look_ahead; i++)
161        {
162          p += accel;
163          height = g1_get_map()->terrain_height(p.x,p.y) + 0.02;
164          if (height>p.z)
165          {
166            accel.set(p.x, p.y, height + (height - p.z));
167            accel -= pos;
168            accel.normalize();
169            p.z = height;
170          }
171        }
172      }
173
174      theta = i4_atan2(vel.y,vel.x);
175      pitch = i4_atan2(-vel.z, sqrt(vel.y*vel.y+vel.x*vel.x));
176    }
177    else
178    {
179      accel.set(cos(theta),
180                sin(theta),
181                0);
182      pitch *= 0.8;
183    }
184    accel *= get_type()->defaults->accel;
185    vel += accel;
186    vel *= damping_fraction;
187  }
188  else
189    vel += i4_3d_vector(0,0,-g1_resources.gravity);
190
191  velocity() = vel;
192 
193  if (move(vel.x,vel.y,vel.z)) 
194  {
195    if (light.get())
196      light->move(x,y,h);
197
198    request_think();
199  }
200
201  pf_missile.stop();
202}
203
204void g1_guided_missile_class::setup(const i4_3d_vector &pos,
205                                    const i4_3d_vector &dir,
206                                    g1_object_class *this_guy_fired_me,
207                                    g1_object_class *track_me)
208{
209  li_class_context context(vars);
210 
211  w32 i;
212
213  x=lx=pos.x;  y=ly=pos.y;  h=lh=pos.z;
214 
215  i4_float start_speed=get_type()->defaults->speed*0.3;
216
217  i4_3d_vector vel(dir);
218 
219  vel.normalize();
220  vel *= start_speed;
221
222  vars->set(velocity,new li_vect(vel));
223
224  vars->set(track_object, new li_g1_ref(track_me));
225  vars->set(who_fired_me, new li_g1_ref(this_guy_fired_me));
226  player_num = this_guy_fired_me->player_num;
227
228  g1_damage_map_struct *dmap=get_type()->get_damage_map(); 
229  fuel() = dmap->range;
230
231  ltheta=theta = i4_atan2(dir.y, dir.x);   
232  pitch=lpitch = i4_atan2(-dir.z, sqrt(dir.x * dir.x + dir.y * dir.y));
233  lroll=roll   = 0;
234 
235  request_think();
236
237  g1_player_info_class *player=g1_player_man.get(player_num);
238
239  if (occupy_location())
240  {
241    start_sounds();
242
243    float r=g1_resources.visual_radius();
244    if (g1_current_view_state()->dist_sqrd(i4_3d_vector(x,y,h))<r*r)
245    {
246      add_smoke();
247      light = (g1_light_object_class *)g1_create_object(g1_get_object_type(light_type.get()));
248      light->setup(x,y,h, 1, 0, 0, 1);
249      light->occupy_location();
250    }
251  }
252}
253
254void g1_guided_missile_class::start_sounds()
255{
256}
257
258void g1_guided_missile_class::add_smoke()
259{
260  int smoke_type=g1_get_object_type(li_smoke_trail.get());
261  g1_smoke_trail_class *st=(g1_smoke_trail_class *)g1_create_object(smoke_type);
262 
263  vars->set(smoke_trail, new li_g1_ref(st));             
264  if (st)
265  {
266    st->setup(x, y, h, 0.02, 0.02, 0xff0000, 0xffffff);   // red to white
267    st->occupy_location();
268  }
269}
270
271void g1_guided_missile_class::update_smoke()
272{
273  li_class_context c(vars);
274
275  if (!smoke_trail())
276    return;
277
278  g1_smoke_trail_class *st=(g1_smoke_trail_class *) smoke_trail()->value();
279  if (st)
280    st->update_head(x,y,h);
281}
282
283void g1_guided_missile_class::delete_smoke()
284{
285  li_class_context c(vars);
286
287  if (!smoke_trail())
288    return;
289
290  g1_smoke_trail_class *st=(g1_smoke_trail_class *) smoke_trail()->value();
291  if (st)
292  {
293    st->unoccupy_location();
294    st->request_remove();
295    vars->set(smoke_trail, li_g1_null_ref());
296  }
297}
298
299void g1_guided_missile_class::add_explode()
300{
301  g1_explosion1_class *explosion;
302
303  int explosion_type=g1_get_object_type(li_explosion1.get());
304  explosion = (g1_explosion1_class *)g1_create_object(explosion_type);
305  if (explosion)
306  {
307    i4_float rx,ry,rh;
308    rx = g1_float_rand(3) * 0.2;
309    ry = g1_float_rand(4) * 0.2;
310    rh = g1_float_rand(9) * 0.2;
311    explosion->setup(x+rx,y+ry,h+rh, g1_explosion1_class::HIT_OBJECT);
312  }
313}
314
315i4_bool g1_guided_missile_class::move(i4_float x_amount,
316                                      i4_float y_amount,
317                                      i4_float z_amount)
318{
319  sw32 res;
320  g1_object_class *hit = NULL;
321
322  i4_3d_vector pos(x,y,h),ray(x_amount, y_amount, z_amount);
323  res = g1_get_map()->check_non_player_collision(player_num,pos, ray, hit);
324 
325  if (res)
326  {
327    g1_apply_damage(this, who_fired_me()->value(), hit, ray);
328
329    if (res != -1)
330      add_explode();
331
332    unoccupy_location();
333    request_remove();
334
335    return i4_F;
336  }
337
338  fuel() -= ray.length();
339  pos += ray;
340 
341  unoccupy_location();
342  x = pos.x;
343  y = pos.y;
344  h = pos.z;
345
346  if (!occupy_location())
347    return i4_F;
348  else
349  {
350    update_smoke();
351    g1_add_to_sound_average(G1_RUMBLE_MISSILE, pos, ray);
352  }
353
354  return i4_T; 
355}
Note: See TracBrowser for help on using the repository browser.