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

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