map_piece.cc 25 KB

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