source: golgotha/src/golg/objs/map_piece.cc

Last change on this file 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: 24.6 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 "objs/map_piece.hh"
10#include "map.hh"
11#include "map_man.hh"
12#include "math/pi.hh"
13#include "math/trig.hh"
14#include "math/angle.hh"
15#include "g1_rand.hh"
16#include "resources.hh"
17#include "objs/model_draw.hh"
18#include "objs/model_id.hh"
19#include "saver.hh"
20#include "objs/scream.hh"
21#include "sound/sfx_id.hh"
22#include "sound_man.hh"
23#include "objs/target.hh"
24#include "player.hh"
25#include "g1_texture_id.hh"
26#include "g1_render.hh"
27#include "sound/sound_types.hh"
28#include "objs/shrapnel.hh"
29#include "objs/explode_model.hh"
30#include "team_api.hh"
31#include "time/profile.hh"
32#include "li_objref.hh"
33#include "lisp/li_types.hh"
34#include "lisp/li_class.hh"
35#include "lisp/li_init.hh"
36#include "objs/path_object.hh"
37#include "tile.hh"
38#include "map_cell.hh"
39#include "tick_count.hh"
40#include "map_view.hh"
41#include "g1_tint.hh"
42#include "controller.hh"
43
44
45int g1_show_list=0;
46li_object *g1_toggle_show_list(li_object *o, li_environment *env)
47{
48  g1_show_list=!g1_show_list;
49  return 0;
50}
51
52li_automatic_add_function(g1_toggle_show_list, "toggle_show_list");
53
54enum { DATA_VERSION=8 };
55
56i4_profile_class pf_find_target("map piece::find target");
57i4_profile_class pf_suggest_move("map_piece::suggest_move");
58i4_profile_class pf_check_move("map_piece::check_move");
59i4_profile_class pf_update_rumble_sound("map_piece::update_rumble");
60i4_profile_class pf_map_piece_think("map_piece::think");
61i4_profile_class pf_map_piece_move("map_piece::move");
62
63
64//S1_SFX(scream1, "screams/scream0_22khz.wav", 0, 60);   // don't play screams as 3d
65//S1_SFX(scream2, "screams/scream00_22khz.wav", 0, 60);
66
67static g1_object_type shrapnel_type=0, shockwave_type=0;
68
69const int battle_step = 9;
70i4_float position_table[battle_step] = { -2.0, -0.5, 1.0, -1.5, 2.0, -2.5, 3.0, -3.5, 4.0 };
71
72
73i4_bool g1_map_piece_class::can_attack(g1_object_class *who) const
74{
75  return (i4_bool)(who->get_team()!=get_team() &&
76                   who->get_flag(TARGETABLE) &&
77                   ((who->get_flag(GROUND | UNDERWATER | AERIAL) &
78                     (get_flag(HIT_GROUND | HIT_UNDERWATER | HIT_AERIAL)>>3)))!=0 &&
79                   in_range(who));
80}
81
82i4_bool g1_map_piece_class::in_range(g1_object_class *o) const
83{
84  float r=detection_range();
85  r*=r;
86  float d=(o->x-x)*(o->x-x) + (o->y-y)*(o->y-y);
87  return (d<=r);
88}
89
90extern g1_object_type g1_supertank_type;
91
92static g1_quad_class mp_tmp_quad;
93
94
95// this is the default function for handling tinted polygons
96g1_quad_class *g1_map_piece_tint_modify(g1_quad_class *in, g1_player_type player)
97{
98  mp_tmp_quad=*in;
99
100  mp_tmp_quad.material_ref=g1_get_texture("charredvehicle");
101  if (g1_tint!=G1_TINT_OFF)
102    g1_render.r_api->set_color_tint(g1_player_tint_handles[player]);
103   
104  return &mp_tmp_quad;
105}
106
107
108void g1_dead_ambient(i4_transform_class *object_to_world,
109                             i4_float &ar, i4_float &ag, i4_float &ab)
110{
111  g1_get_map()->get_illumination_light(object_to_world->t.x, object_to_world->t.y, ar,ag,ab);
112 
113  ar *=0.4;
114  ag *=0.4;
115  ab *=0.4;
116}
117
118void g1_map_piece_class::draw(g1_draw_context_class *context)
119{
120  if (g1_show_list)
121  {
122  if (next_object.get())
123    g1_render.render_3d_line(i4_3d_point_class(x+0.1,y+0.1,h+0.1),
124                             i4_3d_point_class(next_object->x,
125                                               next_object->y+0.1,
126                                               next_object->h+0.1),
127                             0xffff, 0, context->transform);
128  if (prev_object.get())
129    g1_render.render_3d_line(i4_3d_point_class(x-0.1,y-0.1,h+0.1),
130                             i4_3d_point_class(prev_object->x,
131                                               prev_object->y-0.1,
132                                               prev_object->h+0.1),
133                             0xff00ff, 0, context->transform);
134  }
135
136  g1_model_draw(this, draw_params, context);
137
138  if (context->draw_editor_stuff)
139  {
140    if (attack_target.valid())
141    {
142      i4_3d_point_class p1(x,y,h+0.1), p2(attack_target->x,attack_target->y,attack_target->h+0.1);
143      g1_render.render_3d_line(p1,p2,0xff8000,0xff0000,context->transform);
144    }
145  }
146}
147
148void g1_map_piece_class::save(g1_saver_class *fp)
149{
150  g1_object_class::save(fp);
151 
152  fp->start_version(DATA_VERSION);
153
154  fp->write_format("ffffffffffff222",
155                   &speed,&vspeed,
156                   &dest_x,&dest_y,&dest_z,
157                   &dest_theta,&fire_delay,
158                   &path_pos, &path_len,
159                   &path_cos, &path_sin, &path_tan_phi,
160                   &stagger,
161                   &draw_params.frame, &draw_params.animation);
162
163  fp->write_reference(attack_target);
164  fp->write_reference(next_object);
165  fp->write_reference(prev_object);
166
167  next_path.save(fp);
168  if (path_to_follow)
169  {
170    g1_id_ref *r;
171    int t=0;
172    for (r=path_to_follow; r->id; r++, t++); 
173    fp->write_16(t);
174    for (r=path_to_follow; r->id; r++)
175      r->save(fp);
176  }
177  else
178    fp->write_16(0);
179 
180  fp->end_version();
181}
182
183void g1_map_piece_class::add_team_flag()
184{
185  int mini_index=num_mini_objects-1;
186
187  if (mini_index>=0 && mini_objects[mini_index].defmodeltype==0)
188  {
189    mini_objects[mini_index].defmodeltype = g1_player_man.get(player_num)->team_flag.value;
190    i4_3d_vector v;
191    if (!draw_params.model->get_mount_point("Flag", v))
192      v.set(0,0,0);
193   
194    mini_objects[mini_index].position(v);
195  }
196}
197
198g1_map_piece_class::g1_map_piece_class(g1_object_type id,
199                                       g1_loader_class *fp)
200  : g1_object_class(id, fp)
201{
202  rumble_type=G1_RUMBLE_GROUND;
203
204  path_to_follow=0;
205 
206  w16 ver=0,data_size;
207  defaults=g1_object_type_array[id]->defaults;
208
209  damage_direction=i4_3d_vector(0,0,1);
210  ticks_to_blink=0;
211 
212  if (fp)
213    fp->get_version(ver,data_size);
214
215  stagger=0;
216
217  switch (ver)
218  {
219    case DATA_VERSION:
220    {
221      fp->read_format("ffffffffffff222",
222                      &speed,&vspeed,
223                      &dest_x,&dest_y,&dest_z,
224                      &dest_theta,&fire_delay,
225                      &path_pos, &path_len,
226                      &path_cos, &path_sin, &path_tan_phi,
227                      &stagger,
228                      &draw_params.frame, &draw_params.animation);
229
230      fp->read_reference(attack_target);
231      fp->read_reference(next_object);
232      fp->read_reference(prev_object);
233
234      next_path.load(fp);
235      int t=fp->read_16();
236      if (t)
237      {
238        path_to_follow=(g1_id_ref *)i4_malloc(sizeof(g1_id_ref)*(t+1),"");
239        for (int i=0; i<t; i++)
240          path_to_follow[i].load(fp);
241
242        path_to_follow[t].id=0;
243      }
244
245       
246    } break;
247
248    case 7:
249    {
250      draw_params.frame=fp->read_16();
251      draw_params.animation=fp->read_16();
252      speed=fp->read_float();
253      fp->read_float();       // remove in next rev.
254      fp->read_float();       // remove in next rev
255      health=fp->read_16();
256      fire_delay=fp->read_16();
257
258      dest_x=fp->read_float();
259      dest_y=fp->read_float();
260
261      fp->read_32();          // fp->read_reference(attack_target); remove
262      fp->read_32();          // fp->read_reference(convoy); remove
263
264      int t=fp->read_16();
265      if (t)
266      {
267        path_to_follow=(g1_id_ref *)i4_malloc(sizeof(g1_id_ref)*(t+1),"");
268        for (int i=0; i<t; i++)
269          path_to_follow[i].load(fp);
270        path_to_follow[t].id=0;
271      }
272       
273    } break;
274
275    default:
276    {
277      if (fp) fp->seek(fp->tell() + data_size);
278
279      health = defaults->health;
280      speed=0;
281      vspeed=0;
282      tread_pan=0;
283      dest_x = dest_y = dest_z = -1;
284      fire_delay=0;     
285      groundpitch = groundroll = 0;
286      memset(&attack_target,0,sizeof(g1_typed_reference_class<g1_object_class>));
287    } break;
288  }
289
290  if (fp)
291    fp->end_version(I4_LF);
292}
293
294
295inline void check_on_map(const i4_3d_vector &v)
296{
297  int vx=i4_f_to_i(v.x), vy=i4_f_to_i(v.y);
298  if (vx<0 || vy<0 || vx>=g1_get_map()->width() || vy>=g1_get_map()->height())
299    i4_error("off map");
300}
301
302
303
304void g1_map_piece_class::damage(g1_object_class *obj, int hp, i4_3d_vector _damage_dir)
305{
306
307
308  g1_object_class::damage(obj, hp, _damage_dir);
309  ticks_to_blink=20;
310
311 
312  if (health<=0)
313  {
314//     if ((g1_tick_counter + global_id)&1)
315//       scream1.play();
316//     else
317//       scream2.play();
318  }
319  else
320    ticks_to_blink=20;
321}
322
323
324void g1_map_piece_class::find_target(i4_bool unfog)
325{
326  pf_find_target.start();
327
328  if (attack_target.valid() &&
329      (!can_attack(attack_target.get()) || !attack_target->get_flag(DANGEROUS)))
330    attack_target = 0;
331
332  if (!find_target_now())
333  {
334    pf_find_target.stop();
335    return;
336  }
337
338  g1_map_class *map = g1_get_map();
339
340  //find a target in range
341  sw32 ix,iy,x_left,x_right,y_top,y_bottom;
342
343  float r=detection_range();
344  x_left   = i4_f_to_i(x-r); if (x_left<0)                x_left=0;
345  x_right  = i4_f_to_i(x+r); if (x_right>=map->width())   x_right=map->width()-1;
346  y_top    = i4_f_to_i(y-r); if (y_top<0)                 y_top=0;
347  y_bottom = i4_f_to_i(y+r); if (y_bottom>=map->height()) y_bottom=map->height()-1;
348
349  if (g1_player_man.local_player != player_num)
350    unfog=i4_F;
351
352
353  g1_object_class *potential_target=0;
354  i4_float dist,target_dist=r*r;
355
356  int fog_rect_x1=10000, fog_rect_y1=10000,
357      fog_rect_x2=-1, fog_rect_y2=-1;
358 
359
360  for (iy=y_top;  iy<=y_bottom; iy++)
361  {
362    g1_map_cell_class *c=map->cell(x_left,iy);
363    for (ix=x_left; ix<=x_right;  ix++)
364    {
365      if (unfog && (c->flags & g1_map_cell_class::FOGGED))
366      {
367        c->unfog(ix, iy);
368        if (ix<fog_rect_x1) fog_rect_x1=ix;
369        if (ix>fog_rect_x2) fog_rect_x2=ix;
370        if (iy<fog_rect_y1) fog_rect_y1=iy;
371        if (iy>fog_rect_y2) fog_rect_y2=iy;
372      }
373
374     
375      if (!attack_target.valid())
376      {
377        g1_object_chain_class *p = c->get_obj_list();
378       
379        while (p)
380        {
381          g1_object_class *o = p->object;
382                   
383          if (can_attack(o) && o->get_flag(DANGEROUS))
384          {
385            dist = (o->x-x)*(o->x-x) + (o->y-y)*(o->y-y);
386            if (dist<target_dist)
387            {
388              potential_target = o;
389              target_dist = dist;
390            }
391          }
392         
393          p = p->next;
394        }
395      }
396      c++;
397    }
398  }
399
400
401  if (fog_rect_x2!=-1)
402    g1_radar_refresh(fog_rect_x1, fog_rect_y1, fog_rect_x2, fog_rect_y2);
403
404  if (!attack_target.valid() && potential_target)
405  {
406    attack_target = potential_target;
407    request_think();
408  }
409
410  pf_find_target.stop();
411}
412
413void g1_map_piece_class::lead_target(i4_3d_point_class &lead, i4_float shot_speed)
414{
415  if (!attack_target.valid())
416    return;
417
418  lead.set(attack_target->x, attack_target->y, attack_target->h);
419
420  g1_map_piece_class *mp = g1_map_piece_class::cast(attack_target.get());
421
422  if (!mp)
423    return;
424
425  if (shot_speed<0)
426  {
427    g1_object_type shot = g1_get_object_type(defaults->fire_type);
428    shot_speed = g1_object_type_array[shot]->get_damage_map()->speed;
429  }
430
431  if (shot_speed>0)
432  {
433    i4_float
434      dx = mp->x - x,
435      dy = mp->y - y,
436      t = sqrt(dx*dx + dy*dy)/shot_speed;
437
438    i4_3d_vector mp_diff(mp->x - mp->lx, mp->y - mp->ly, mp->h - mp->lh);
439    mp_diff*=t;
440    lead += mp_diff;
441  }
442}
443
444
445
446void g1_map_piece_class::init()
447{
448
449}
450
451
452void g1_map_piece_class::init_rumble_sound(g1_rumble_type type)
453{
454  rumble_type=type;
455}
456
457
458
459
460static li_object_class_member links("links");
461static li_symbol_ref reached("reached");
462
463void g1_map_piece_class::unlink()
464{
465  g1_path_object_class *path;
466  g1_map_piece_class *mp;
467
468  if (path = g1_path_object_class::cast(prev_object.get()))
469  {
470    int i=path->get_object_index(this);
471    if (i>=0)
472      path->link[i].object = next_object.get();
473    else
474      i4_warning("unlinking bad link!");
475  }
476  else if (mp = g1_map_piece_class::cast(prev_object.get()))
477    if (mp->next_path.get() == next_path.get())
478      mp->next_object = next_object.get();
479    else
480      mp->prev_object = next_object.get();
481
482  if (path = g1_path_object_class::cast(next_object.get()))
483  {
484    int i=path->get_object_index(this);
485    if (i>=0)
486      path->link[i].object = prev_object.get();
487    else
488      i4_warning("unlinking bad link!");
489  }
490  else if (mp = g1_map_piece_class::cast(next_object.get()))
491    if (mp->next_path.get() == next_path.get())
492      mp->prev_object = prev_object.get();
493    else
494      mp->next_object = prev_object.get();
495
496  prev_object=0;
497  next_object=0;
498}
499
500void g1_map_piece_class::link(g1_object_class *origin)
501{
502  g1_object_class *origin_next=0;
503  g1_path_object_class *path;
504  g1_map_piece_class *mp;
505
506  if (path = g1_path_object_class::cast(origin))
507  {
508    int i = path->get_path_index(g1_path_object_class::cast(next_path.get()));
509    if (i>=0)
510    {
511      origin_next = path->link[i].object.get();
512      path->link[i].object = this;
513    }
514    else
515      i4_warning("linking bad link!");
516  }
517  else if (mp = g1_map_piece_class::cast(origin))
518  {
519    if (mp->next_path.get() == next_path.get())
520    {
521      origin_next = mp->next_object.get();
522      mp->next_object = this;
523    }
524    else
525    {
526      origin_next = mp->prev_object.get();
527      mp->prev_object = this;
528    }
529  }
530
531  if (path = g1_path_object_class::cast(origin_next))
532  {
533    int i=path->get_object_index(origin);
534    if (i>=0)
535      path->link[i].object = this;
536    else
537      i4_warning("linking bad link!");
538  }
539  else if (mp = g1_map_piece_class::cast(origin_next))
540    if (mp->next_path.get() == next_path.get())
541      mp->prev_object = this;
542    else
543      mp->next_object = this;
544
545  next_object = origin_next;
546  prev_object = origin;
547}
548
549void g1_map_piece_class::think()
550{
551  pf_map_piece_think.start();
552
553  request_think();
554
555  pitch = 0;
556  roll  = 0;
557
558  // limit the search for target to 1 every 4 ticks
559  find_target();
560
561  if (fire_delay>0)
562    fire_delay--;
563 
564  if (next_path.valid())
565  {
566    dest_x = next_path->x;
567    dest_y = next_path->y;
568  }
569
570  i4_float dist, dtheta, dx, dy, old_pathpos=path_pos;
571  suggest_move(dist, dtheta, dx, dy, 0);
572  if (check_move(dx,dy))
573  {
574    if ((g1_rand(62)&63)==0)
575    {
576      g1_camera_event cev;
577      cev.type=G1_WATCH_IDLE;
578      cev.follow_object=this;
579      g1_current_view_state()->suggest_camera_event(cev);
580    }
581   
582    move(dx,dy);
583  }
584  else
585  {
586    get_terrain_info();
587    path_pos = old_pathpos;
588  }
589  if (dist<speed)
590    advance_path();
591 
592  if (h+vspeed-0.001 > terrain_height)
593  {
594    //he's off the ground
595    //dont set these to 0, just leave them the way they were
596    groundpitch = lgroundpitch;
597    groundroll  = lgroundroll;
598
599    h += vspeed;
600    vspeed -= g1_resources.gravity;   
601    request_think();
602  }
603  else
604  {
605    if (!get_flag(ON_WATER))
606      h = terrain_height;
607    else
608    {
609      h -= g1_resources.sink_rate;
610      damage(0,g1_resources.water_damage,i4_3d_vector(0,0,1));
611    }
612   
613    if (h!=lh)
614      hit_ground();
615   
616    vspeed = h - lh - g1_resources.gravity;
617  }
618
619  pf_map_piece_think.stop();
620}
621
622i4_bool g1_map_piece_class::find_target_now() const
623{
624  return (((g1_tick_counter+global_id)&3)==0);
625}
626
627void g1_map_piece_class::hit_ground()
628{
629  if (vspeed<-0.4)
630    damage(0,health,i4_3d_vector(0,0,1));
631}
632
633void g1_map_piece_class::advance_path()
634{
635  g1_team_type type=g1_player_man.get(player_num)->get_team();
636     
637  if (next_path.valid())
638  {
639    message(reached.get(), new li_g1_ref(next_path->global_id), 0);
640
641    unlink();
642
643    g1_path_object_class *from = g1_path_object_class::cast(next_path.get());
644
645    // find next path node to go to
646    if (path_to_follow)
647    {
648      g1_id_ref *r;
649      for (r=path_to_follow; r->id && r->id!=next_path.id; r++);
650      if (r->id) r++;
651      if (r->id)
652        next_path=*r;
653      else
654        next_path.id=0;
655    }
656
657    if (next_path.valid())
658    {
659      g1_path_object_class *next=(g1_path_object_class *)next_path.get();
660
661      path_cos = next->x - from->x;
662      path_sin = next->y - from->y;
663      path_tan_phi = next->h - from->h;
664      stagger = g1_float_rand(8)*2.0-1.0;
665
666      path_pos = 0;
667     
668      path_len = sqrt(path_cos*path_cos + path_sin*path_sin);
669      i4_float dist_w = 1.0/path_len;
670      path_cos *= dist_w;
671      path_sin *= dist_w;
672      path_tan_phi *= dist_w;
673
674      link(from);
675    }
676    else
677    {
678      unoccupy_location();
679      request_remove();
680    }
681  }
682}
683
684
685
686i4_bool g1_map_piece_class::check_turn_radius()
687//{{{
688
689  i4_float cx,cy;
690  i4_float r,d,d1,d2,rx,ry;
691 
692  //get the radius of the circle he's currently capable of turning through 
693  //make it extra-large so he doesnt make ridiculously large turns
694  //check r^2... a bit faster
695  r = (speed/defaults->turn_speed) * 1.5;
696
697  rx = r*sin(theta);
698  ry = r*cos(theta);
699
700  r = r*r;
701 
702  //check the two circles that are currently unreachable
703  //if the destination lies within either circle, return false 
704  cx = x - rx;
705  cy = y + ry;
706  d1 = (dest_x - cx);
707  d1 *= d1;
708  d2 = (dest_y - cy);
709  d2 *= d2;
710  d  = d1+d2;
711  if (d<r) return i4_F; 
712   
713  cx = x + rx;
714  cy = y - ry;
715  d1 = (dest_x - cx);
716  d1 *= d1;
717  d2 = (dest_y - cy);
718  d2 *= d2;
719  d  = d1+d2;
720  if (d<r) return i4_F;
721 
722  return i4_T;
723}
724//}}}
725
726void g1_map_piece_class::request_remove()
727//{{{
728{
729  if (path_to_follow)
730    i4_free(path_to_follow);
731  path_to_follow = 0;
732  unlink();
733  g1_object_class::request_remove();
734}
735//}}}
736
737i4_bool g1_map_piece_class::suggest_move(i4_float &dist,
738                                         i4_float &dtheta,
739                                         i4_float &dx, i4_float &dy,
740                                         i4_float braking_friction,
741                                         i4_bool reversible)
742{
743  if (!prev_object.get() || !next_object.get())
744  {
745    dx=dy=0;
746    return i4_F;
747  }
748
749  pf_suggest_move.start();
750
751  i4_float angle, scale=0.0;
752
753  speed = defaults->speed * (1.0-damping_fraction);
754
755
756  if (path_len>6.0)
757  {
758    if (path_pos<3.0)
759      scale = path_pos/3.0;
760    else if (path_pos>path_len-3.0)
761      scale = (path_len-path_pos)/3.0;
762    else
763      scale = 1.0;
764  }
765
766  path_pos += speed;
767  dx = (dest_x - path_cos*(path_len - path_pos) - path_sin*stagger*scale - x);
768  dy = (dest_y - path_sin*(path_len - path_pos) + path_cos*stagger*scale - y);
769
770  //aim the vehicle   
771  angle = i4_atan2(dy,dx);
772  i4_normalize_angle(angle);   
773 
774  dtheta = angle - theta;
775  if (dtheta<-i4_pi()) dtheta += 2*i4_pi();
776  else if (dtheta>i4_pi()) dtheta -= 2*i4_pi();
777
778  if (dtheta<-defaults->turn_speed) dtheta = -defaults->turn_speed;
779  else if (dtheta>defaults->turn_speed) dtheta = defaults->turn_speed;
780  theta += dtheta;
781  i4_normalize_angle(theta);
782
783  dist = path_len-path_pos;
784
785  pf_suggest_move.stop();
786  return (dist==0);
787}
788
789i4_bool g1_map_piece_class::suggest_air_move(i4_float &dist,
790                                             i4_float &dtheta,
791                                             i4_3d_vector &d)
792{
793  pf_suggest_move.start();
794
795  i4_float angle, scale=0.0;
796
797  speed = defaults->speed;
798
799  if (path_len>6.0)
800  {
801    if (path_pos<3.0)
802      scale = path_pos/3.0;
803    else if (path_pos>path_len-3.0)
804      scale = (path_len-path_pos)/3.0;
805    else
806      scale = 1.0;
807  }
808
809  path_pos += speed;
810  d.x = (dest_x - path_cos*(path_len - path_pos) - path_sin*stagger*scale - x);
811  d.y = (dest_y - path_sin*(path_len - path_pos) + path_cos*stagger*scale - y);
812  d.z = (dest_z - path_tan_phi*(path_len - path_pos) - h);
813
814  //aim the vehicle   
815  angle = i4_atan2(d.y,d.x);
816  i4_normalize_angle(angle);   
817 
818  dtheta = angle - theta;
819  if (dtheta<-i4_pi()) dtheta += 2*i4_pi();
820  else if (dtheta>i4_pi()) dtheta -= 2*i4_pi();
821
822  if (dtheta<-defaults->turn_speed) dtheta = -defaults->turn_speed;
823  else if (dtheta>defaults->turn_speed) dtheta = defaults->turn_speed;
824  theta += dtheta;
825  i4_normalize_angle(theta);
826
827  dist = path_len-path_pos;
828
829  pf_suggest_move.stop();
830  return (dist==0);
831}
832
833i4_bool g1_map_piece_class::check_move(i4_float dx,i4_float dy) const
834{
835  pf_check_move.start();
836  i4_bool ret=i4_T;
837  if (next_object.valid())
838  {
839    g1_path_object_class *path;
840    g1_map_piece_class *mp;
841   
842    if (path = g1_path_object_class::cast(next_object.get()))
843    {
844      g1_team_type team=g1_player_man.get(player_num)->get_team();
845   
846      // check branches
847      for (int i=0; i<path->total_links(team); i++)
848      {
849        mp = g1_map_piece_class::cast(path->get_object_link(team,i));
850
851        if (mp)
852        {
853          i4_float dist=path_len - path_pos;
854         
855          if (mp->player_num!=player_num)
856          {
857            // enemy vehicle
858            dist+=mp->path_len-mp->path_pos;
859            if (dist<2)
860              ret=i4_F;
861          }
862          else
863          {
864            // allied vehicle
865            dist += mp->path_pos;
866            if (dist<0.5)
867              ret=i4_F;
868          }
869        }
870      }
871    }
872    else if (mp = g1_map_piece_class::cast(next_object.get()))
873    {
874      i4_float dist = -path_pos;
875     
876      if (mp->player_num!=player_num)
877      {
878        // enemy vehicle
879        dist+=mp->path_len-mp->path_pos;
880        if (dist<2)
881          ret=i4_F;
882      }
883      else
884      {
885        // allied vehicle
886        dist += mp->path_pos;
887        if (dist<0.5)
888          ret=i4_F;
889      }
890    }
891  }
892  pf_check_move.stop();
893  return ret;
894}
895
896i4_bool g1_map_piece_class::check_life(i4_bool remove_if_dead)
897{
898  if (ticks_to_blink)
899    ticks_to_blink--;
900
901  if (health<=0)
902  {
903    //they were just killed. free their resources
904    if (remove_if_dead)
905    {
906      unoccupy_location();
907      request_remove();
908
909      //keep thinking so that death scenes can be played out
910    }
911
912
913    char msg[100];
914    sprintf(msg, "Unit Lost : %s", name());
915    g1_player_man.show_message(msg, 0xff0000, player_num);
916   
917    return i4_F;
918  }
919  return i4_T;
920}
921
922static li_symbol_ref explode_model("explode_model");
923
924
925 
926static li_symbol_ref set_course("set_course");
927
928void g1_map_piece_class::set_path(g1_id_ref *list)
929{
930  if (path_to_follow)
931    i4_free(path_to_follow);
932     
933  path_to_follow=list;
934  next_path=list[0].id;
935 
936  advance_path();
937  if (!next_path.valid())
938    i4_warning("i can't get there!");
939  ltheta = theta = i4_atan2(path_sin,path_cos);
940  request_think();
941}
942
943
944
945i4_bool g1_map_piece_class::move(i4_float x_amount,
946                             i4_float y_amount)
947{
948  pf_map_piece_move.start(); 
949
950  unoccupy_location();
951 
952  x += x_amount;
953  y += y_amount;
954 
955  if (!occupy_location())
956  {
957    pf_map_piece_move.stop();
958    return i4_F; 
959  }
960
961  g1_add_to_sound_average(rumble_type, i4_3d_vector(x,y,h));
962
963
964  pf_map_piece_move.stop();
965
966  return i4_T;
967}
968
969void g1_map_piece_class::get_terrain_info()
970{
971  sw32 ix,iy;
972 
973  ix=i4_f_to_i(x);
974  iy=i4_f_to_i(y);
975  g1_map_cell_class *cell_on=g1_get_map()->cell(ix,iy);
976 
977  w16 handle=cell_on->type;
978  i4_float newheight;
979 
980  g1_get_map()->calc_height_pitch_roll(x,y,h, terrain_height, groundpitch, groundroll);
981
982  g1_tile_class *t = g1_tile_man.get(handle);
983  damping_fraction = t->friction_fraction;
984  set_flag(ON_WATER, (t->flags & g1_tile_class::WAVE)!=0 &&
985           terrain_height<=g1_get_map()->terrain_height(x,y));
986}
987
988void g1_map_piece_class::calc_world_transform(i4_float ratio, i4_transform_class *t)
989{
990  if (!t)
991    t = world_transform;
992
993  i4_float z_rot        = i4_interpolate_angle(ltheta,theta, ratio);
994  i4_float y_rot        = i4_interpolate_angle(lpitch,pitch, ratio);
995  i4_float x_rot        = i4_interpolate_angle(lroll ,roll , ratio);
996 
997  i4_float ground_x_rot = i4_interpolate_angle(lgroundroll,  groundroll, ratio);
998  i4_float ground_y_rot = i4_interpolate_angle(lgroundpitch, groundpitch, ratio);
999
1000  i4_float tx=i4_interpolate(lx,x,ratio);
1001  i4_float ty=i4_interpolate(ly,y,ratio);
1002  i4_float tz=i4_interpolate(lh,h,ratio);
1003
1004 
1005  t->translate(tx,ty,tz); 
1006  t->mult_rotate_x(ground_x_rot);
1007  t->mult_rotate_y(ground_y_rot);
1008  t->mult_rotate_z(z_rot);
1009  t->mult_rotate_y(y_rot);
1010  t->mult_rotate_x(x_rot);
1011}
Note: See TracBrowser for help on using the repository browser.