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 "input.hh"
|
---|
11 | #include "math/pi.hh"
|
---|
12 | #include "math/angle.hh"
|
---|
13 | #include "math/random.hh"
|
---|
14 | #include "resources.hh"
|
---|
15 | #include "saver.hh"
|
---|
16 | #include "map.hh"
|
---|
17 | #include "map_cell.hh"
|
---|
18 | #include "map_man.hh"
|
---|
19 | #include "sound/sfx_id.hh"
|
---|
20 | #include "g1_speed.hh"
|
---|
21 | #include "math/trig.hh"
|
---|
22 | #include "g1_render.hh"
|
---|
23 | #include "r1_api.hh"
|
---|
24 | #include "tile.hh"
|
---|
25 | #include "object_definer.hh"
|
---|
26 | #include "player.hh"
|
---|
27 | #include "human.hh"
|
---|
28 | #include "controller.hh"
|
---|
29 | #include "g1_render.hh"
|
---|
30 | #include "statistics.hh"
|
---|
31 | #include "human.hh"
|
---|
32 |
|
---|
33 | #include "objs/model_id.hh"
|
---|
34 | #include "objs/stank.hh"
|
---|
35 |
|
---|
36 | #include "objs/explosion1.hh"
|
---|
37 | #include "objs/shrapnel.hh"
|
---|
38 | #include "objs/fire.hh"
|
---|
39 | #include "lisp/lisp.hh"
|
---|
40 | #include "lisp/li_load.hh"
|
---|
41 | #include "tick_count.hh"
|
---|
42 |
|
---|
43 | #include "time/profile.hh"
|
---|
44 | #include "map_cell.hh"
|
---|
45 | #include "r1_clip.hh"
|
---|
46 | #include "lisp/li_error.hh"
|
---|
47 | #include "objs/vehic_sounds.hh"
|
---|
48 | #include "map_view.hh"
|
---|
49 |
|
---|
50 | #include "image_man.hh"
|
---|
51 |
|
---|
52 | #include "g1_tint.hh"
|
---|
53 | #include "objs/carcass.hh"
|
---|
54 |
|
---|
55 | static i4_float droll = 0.0, ddroll = 0.0, hurt=0.0;
|
---|
56 |
|
---|
57 | static g1_model_ref model_ref("supertankbase"),
|
---|
58 | turret_ref("supertanktop"),
|
---|
59 | stank_carcass("chunk_supertankbase");
|
---|
60 |
|
---|
61 | static i4_3d_vector turret_attach, muzzle_exit;
|
---|
62 |
|
---|
63 | static g1_team_icon_ref radar_im0("bitmaps/radar/supertank_0.tga");
|
---|
64 | static g1_team_icon_ref radar_im2("bitmaps/radar/supertank_2.tga");
|
---|
65 | static g1_team_icon_ref radar_im4("bitmaps/radar/supertank_4.tga");
|
---|
66 | static g1_team_icon_ref radar_im6("bitmaps/radar/supertank_6.tga");
|
---|
67 | static g1_team_icon_ref radar_im8("bitmaps/radar/supertank_8.tga");
|
---|
68 | static g1_team_icon_ref radar_im10("bitmaps/radar/supertank_10.tga");
|
---|
69 | static g1_team_icon_ref radar_im12("bitmaps/radar/supertank_12.tga");
|
---|
70 | static g1_team_icon_ref radar_im14("bitmaps/radar/supertank_14.tga");
|
---|
71 |
|
---|
72 | S1_SFX(supertank_lost, "narrative/supertank_lost_22khz.wav", S1_STREAMED, 200);
|
---|
73 | S1_SFX(return_to_repair, "computer_voice/return_to_base_for_repairs_22khz.wav", S1_STREAMED, 200);
|
---|
74 |
|
---|
75 | i4_profile_class pf_stank_think("stank::think");
|
---|
76 |
|
---|
77 | g1_object_type g1_supertank_type;
|
---|
78 |
|
---|
79 | static g1_object_type main_base_type;
|
---|
80 |
|
---|
81 | void g1_supertank_init();
|
---|
82 |
|
---|
83 | g1_object_definer<g1_player_piece_class>
|
---|
84 | g1_supertank_def("stank",
|
---|
85 | g1_object_definition_class::MOVABLE |
|
---|
86 | g1_object_definition_class::TO_MAP_PIECE |
|
---|
87 | g1_object_definition_class::TO_PLAYER_PIECE,
|
---|
88 | g1_supertank_init);
|
---|
89 |
|
---|
90 | void g1_supertank_init()
|
---|
91 | {
|
---|
92 | g1_supertank_type = g1_supertank_def.type;
|
---|
93 | main_base_type = g1_get_object_type("mainbasepad");
|
---|
94 |
|
---|
95 | turret_attach = g1_resources.player_top_attach;
|
---|
96 | model_ref()->get_mount_point("Turret", turret_attach);
|
---|
97 | muzzle_exit.set(0.4, 0, 0.11);
|
---|
98 | turret_ref()->get_mount_point("Muzzle", muzzle_exit);
|
---|
99 | }
|
---|
100 |
|
---|
101 |
|
---|
102 | void g1_player_piece_class::save_base_info(g1_saver_class *fp)
|
---|
103 | {
|
---|
104 | fp->start_version(BASE_DATA_VERSION);
|
---|
105 | fp->write_format("ffff44",
|
---|
106 | &base_angle, &lbase_angle, &strafe_speed, &cur_top_attach,
|
---|
107 | &move_tick,
|
---|
108 | &upgrade_level_when_built);
|
---|
109 | fp->end_version();
|
---|
110 | }
|
---|
111 |
|
---|
112 | void g1_player_piece_class::load_base_info(g1_loader_class *fp)
|
---|
113 | {
|
---|
114 | if (fp && fp->check_version(BASE_DATA_VERSION))
|
---|
115 | {
|
---|
116 | fp->read_format("ffff44",
|
---|
117 | &base_angle, &lbase_angle, &strafe_speed, &cur_top_attach,
|
---|
118 | &move_tick,
|
---|
119 | &upgrade_level_when_built);
|
---|
120 | fp->end_version(I4_LF);
|
---|
121 |
|
---|
122 | }
|
---|
123 | else
|
---|
124 | {
|
---|
125 | base_angle=lbase_angle=0;
|
---|
126 | strafe_speed=0;
|
---|
127 | cur_top_attach=g1_resources.player_top_attach.z;
|
---|
128 | move_tick=0;
|
---|
129 | }
|
---|
130 | }
|
---|
131 |
|
---|
132 |
|
---|
133 | void g1_player_piece_class::save_mouse_look_info(g1_saver_class *fp)
|
---|
134 | {
|
---|
135 | fp->start_version(MOUSE_LOOK_DATA_VERSION);
|
---|
136 |
|
---|
137 | fp->write_float(mouse_look_increment_x);
|
---|
138 | fp->write_float(mouse_look_increment_y);
|
---|
139 | fp->write_float(mouse_look_x);
|
---|
140 | fp->write_float(mouse_look_y);
|
---|
141 |
|
---|
142 | fp->write_float(turret->rotation.z);
|
---|
143 |
|
---|
144 | fp->end_version();
|
---|
145 | }
|
---|
146 |
|
---|
147 | void g1_player_piece_class::load_mouse_look_info(g1_loader_class *fp)
|
---|
148 | {
|
---|
149 | if (fp && fp->check_version(MOUSE_LOOK_DATA_VERSION))
|
---|
150 | {
|
---|
151 | mouse_look_increment_x=fp->read_float();
|
---|
152 | mouse_look_increment_y=fp->read_float();
|
---|
153 | mouse_look_x=fp->read_float();
|
---|
154 | mouse_look_y=fp->read_float();
|
---|
155 |
|
---|
156 | turret->rotation.z=fp->read_float();
|
---|
157 | fp->end_version(I4_LF);
|
---|
158 | }
|
---|
159 | else
|
---|
160 | {
|
---|
161 | mouse_look_increment_x=mouse_look_increment_y=0;
|
---|
162 | mouse_look_x=mouse_look_y=0;
|
---|
163 | turret->rotation.z=0;
|
---|
164 | }
|
---|
165 | }
|
---|
166 |
|
---|
167 |
|
---|
168 | void g1_player_piece_class::save_ammo_info(g1_saver_class *fp)
|
---|
169 | {
|
---|
170 | fp->start_version(AMMO_DATA_VERSION);
|
---|
171 | for (int i=0; i<MAX_WEAPONS; i++)
|
---|
172 | ammo[i].save(fp);
|
---|
173 | fp->end_version();
|
---|
174 | }
|
---|
175 |
|
---|
176 | void g1_player_piece_class::load_ammo_info(g1_loader_class *fp)
|
---|
177 | {
|
---|
178 | if (fp && fp->check_version(AMMO_DATA_VERSION))
|
---|
179 | {
|
---|
180 | for (int i=0; i<MAX_WEAPONS; i++)
|
---|
181 | ammo[i].load(fp);
|
---|
182 | fp->end_version(I4_LF);
|
---|
183 | }
|
---|
184 | }
|
---|
185 |
|
---|
186 | void g1_player_piece_class::save(g1_saver_class *fp)
|
---|
187 | {
|
---|
188 | g1_map_piece_class::save(fp);
|
---|
189 |
|
---|
190 | int han=fp->mark_size();
|
---|
191 |
|
---|
192 | fp->start_version(DATA_VERSION);
|
---|
193 | fp->write_32(stank_flags);
|
---|
194 | fp->write_float(vspeed);
|
---|
195 | fp->end_version();
|
---|
196 |
|
---|
197 | save_base_info(fp);
|
---|
198 | save_mouse_look_info(fp);
|
---|
199 | save_ammo_info(fp);
|
---|
200 |
|
---|
201 | fp->end_mark_size(han);
|
---|
202 | }
|
---|
203 |
|
---|
204 |
|
---|
205 | void g1_stank_ammo_info_struct::setup(li_symbol *sym)
|
---|
206 | {
|
---|
207 | ammo_type=g1_find_stank_ammo_type(sym);
|
---|
208 | if (ammo_type)
|
---|
209 | amount=ammo_type->max_amount;
|
---|
210 | else
|
---|
211 | li_error(0,"s_tank : no weapon called %O", sym);
|
---|
212 |
|
---|
213 | delay_remaining=0;
|
---|
214 | need_refresh=i4_T;
|
---|
215 | last_fired_object=0;
|
---|
216 | }
|
---|
217 |
|
---|
218 | void g1_player_piece_class::find_weapons()
|
---|
219 | {
|
---|
220 | int level=g1_player_man.get_local()->supertank_upgrade_level;
|
---|
221 | if (level<0) level=0;
|
---|
222 | upgrade_level_when_built=level;
|
---|
223 |
|
---|
224 |
|
---|
225 | li_object *o;
|
---|
226 | for (o=li_get_value("upgrade_levels"); o && li_cdr(o,0) && level; level--)
|
---|
227 | o=li_cdr(o,0);
|
---|
228 |
|
---|
229 | if (o)
|
---|
230 | {
|
---|
231 | o=li_cdr(li_car(o,0),0);
|
---|
232 |
|
---|
233 | for (int i=0; i<MAX_WEAPONS; i++)
|
---|
234 | {
|
---|
235 | ammo[i].setup(li_symbol::get(li_car(o,0),0));
|
---|
236 | o=li_cdr(o,0);
|
---|
237 | }
|
---|
238 | }
|
---|
239 | }
|
---|
240 |
|
---|
241 |
|
---|
242 |
|
---|
243 | void g1_stank_ammo_info_struct::save(g1_saver_class *fp)
|
---|
244 | {
|
---|
245 | if (ammo_type)
|
---|
246 | li_save_object(fp, ammo_type->weapon_type,0);
|
---|
247 | else
|
---|
248 | li_save_object(fp, li_nil,0);
|
---|
249 |
|
---|
250 |
|
---|
251 | fp->write_16(amount);
|
---|
252 | fp->write_16(delay_remaining);
|
---|
253 | fp->write_8(need_refresh);
|
---|
254 |
|
---|
255 | fp->write_reference(last_fired_object);
|
---|
256 | }
|
---|
257 |
|
---|
258 | void g1_stank_ammo_info_struct::load(g1_loader_class *fp)
|
---|
259 | {
|
---|
260 | li_symbol *wtype=li_symbol::get(li_load_object(fp, fp->li_remap, 0),0);
|
---|
261 |
|
---|
262 | ammo_type=g1_find_stank_ammo_type(wtype);
|
---|
263 | amount=fp->read_16();
|
---|
264 | delay_remaining=fp->read_16();
|
---|
265 | need_refresh=fp->read_8();
|
---|
266 | fp->read_reference(last_fired_object);
|
---|
267 | }
|
---|
268 |
|
---|
269 |
|
---|
270 | g1_player_piece_class::g1_player_piece_class(g1_object_type id,
|
---|
271 | g1_loader_class *fp)
|
---|
272 | : g1_map_piece_class(id, fp), path(0)
|
---|
273 | {
|
---|
274 | w16 ver,data_size;
|
---|
275 | i4_bool defaults=i4_T;
|
---|
276 |
|
---|
277 | draw_params.setup(model_ref.id());
|
---|
278 |
|
---|
279 | allocate_mini_objects(1,"Super Tank Mini Objects");
|
---|
280 | turret = &mini_objects[0];
|
---|
281 | turret->defmodeltype = turret_ref.id();
|
---|
282 | turret->position(turret_attach);
|
---|
283 |
|
---|
284 | if (fp)
|
---|
285 | {
|
---|
286 | int total_size=fp->read_32();
|
---|
287 |
|
---|
288 | if (fp->check_version(DATA_VERSION))
|
---|
289 | {
|
---|
290 | stank_flags = fp->read_32();
|
---|
291 | vspeed = fp->read_float();
|
---|
292 | fp->end_version(I4_LF);
|
---|
293 |
|
---|
294 | find_weapons();
|
---|
295 |
|
---|
296 | load_base_info(fp);
|
---|
297 | load_mouse_look_info(fp);
|
---|
298 | load_ammo_info(fp);
|
---|
299 | defaults=i4_F;
|
---|
300 | }
|
---|
301 | else
|
---|
302 | fp->seek(fp->tell() + total_size);
|
---|
303 | }
|
---|
304 |
|
---|
305 | if (defaults)
|
---|
306 | {
|
---|
307 | find_weapons();
|
---|
308 | stank_flags=0;
|
---|
309 | vspeed=0;
|
---|
310 |
|
---|
311 | load_base_info(0);
|
---|
312 | load_mouse_look_info(0);
|
---|
313 | load_ammo_info(0);
|
---|
314 |
|
---|
315 | health=ammo[3].amount;
|
---|
316 | }
|
---|
317 |
|
---|
318 | turret_kick = lturret_kick = 0;
|
---|
319 |
|
---|
320 | // clear user data
|
---|
321 | accel_ratio = strafe_accel_ratio = dtheta = 0;
|
---|
322 | memset(fire,0,sizeof(fire));
|
---|
323 |
|
---|
324 | init_rumble_sound(G1_RUMBLE_STANK);
|
---|
325 |
|
---|
326 | radar_image=&radar_im0;
|
---|
327 | radar_type=G1_RADAR_STANK;
|
---|
328 | //initialize these guys. somewhat important
|
---|
329 | set_flag(GROUND |
|
---|
330 | BLOCKING |
|
---|
331 | SELECTABLE |
|
---|
332 | TARGETABLE |
|
---|
333 | GROUND |
|
---|
334 | HIT_AERIAL |
|
---|
335 | HIT_GROUND |
|
---|
336 | DANGEROUS, 1);
|
---|
337 |
|
---|
338 | }
|
---|
339 |
|
---|
340 | i4_bool g1_player_piece_class::suggest_move(i4_float &dist,
|
---|
341 | i4_float &dtheta,
|
---|
342 | i4_float &dx, i4_float &dy,
|
---|
343 | i4_float braking_friction)
|
---|
344 | {
|
---|
345 | i4_float angle,t ,diffangle;
|
---|
346 |
|
---|
347 | i4_bool go_reverse = i4_F;
|
---|
348 | i4_bool can_get_there = i4_T;
|
---|
349 |
|
---|
350 | dx = (dest_x - x);
|
---|
351 | dy = (dest_y - y);
|
---|
352 |
|
---|
353 | //aim the vehicle
|
---|
354 | angle = i4_atan2(dy,dx);
|
---|
355 | i4_normalize_angle(angle);
|
---|
356 |
|
---|
357 | diffangle = angle - theta;
|
---|
358 | if (diffangle<-i4_pi()) diffangle += 2*i4_pi();
|
---|
359 | else if (diffangle>i4_pi()) diffangle -= 2*i4_pi();
|
---|
360 |
|
---|
361 | go_reverse = (diffangle>i4_pi()/2) || (diffangle<-i4_pi()/2);
|
---|
362 |
|
---|
363 | //dont worry about turn radii unless he's actually ready for forward movement
|
---|
364 | if (go_reverse)
|
---|
365 | dtheta = diffangle;
|
---|
366 | else
|
---|
367 | {
|
---|
368 | can_get_there = check_turn_radius();
|
---|
369 | dtheta = diffangle;
|
---|
370 | }
|
---|
371 |
|
---|
372 | //distance to move squared
|
---|
373 | t = dx*dx + dy*dy;
|
---|
374 |
|
---|
375 | //how far will the vehicle go if he slows down from his maximum speed?
|
---|
376 | if (t>speed*speed+0.0025 || braking_friction==0.0)
|
---|
377 | {
|
---|
378 | if (dtheta<-defaults->turn_speed) dtheta = -defaults->turn_speed;
|
---|
379 | else if (dtheta>defaults->turn_speed) dtheta = defaults->turn_speed;
|
---|
380 | theta += dtheta;
|
---|
381 | i4_normalize_angle(theta);
|
---|
382 |
|
---|
383 | i4_float stop_dist;
|
---|
384 | if (braking_friction>0.0)
|
---|
385 | stop_dist = fabs(speed)/braking_friction; // geometric series of braking motion
|
---|
386 |
|
---|
387 | if (!go_reverse && braking_friction>0.0 && t<=(stop_dist*stop_dist))
|
---|
388 | {
|
---|
389 | //just in case our calculations were off, dont let him slow to less than 0.01
|
---|
390 | if (speed <= 0.01)
|
---|
391 | speed = 0.01;
|
---|
392 | else
|
---|
393 | speed *= (1.0-braking_friction);
|
---|
394 | }
|
---|
395 | else
|
---|
396 | {
|
---|
397 | // calculate speed changes
|
---|
398 |
|
---|
399 | // uA = coefficient of sliding friction (removed for now)
|
---|
400 | // th = rising pitch
|
---|
401 | // uB = damping friction (damping_fraction = 1/uB)
|
---|
402 | // C = exp( -uB * t) (damping_e)
|
---|
403 |
|
---|
404 | // K = (accel - (uA*cos(th) + sin(th))*g
|
---|
405 | // finalvel = K / uB
|
---|
406 |
|
---|
407 | // vel = finalvel - (speed - finalvel)*exp(-uB * step_time)
|
---|
408 |
|
---|
409 | i4_float target_speed, accel;
|
---|
410 |
|
---|
411 | if (!can_get_there && !go_reverse)
|
---|
412 | speed *= (1.0-braking_friction);
|
---|
413 | else
|
---|
414 | {
|
---|
415 | if (go_reverse)
|
---|
416 | accel = -defaults->accel*0.30;
|
---|
417 | else
|
---|
418 | accel = defaults->accel;
|
---|
419 |
|
---|
420 | accel += sin(pitch)*g1_resources.gravity;
|
---|
421 | speed += accel;
|
---|
422 | speed -= speed*damping_fraction;
|
---|
423 | }
|
---|
424 | }
|
---|
425 | dist = speed*cos(pitch);
|
---|
426 | dx = cos(theta) * dist;
|
---|
427 | dy = sin(theta) * dist;
|
---|
428 | dist = t;
|
---|
429 | }
|
---|
430 | else
|
---|
431 | {
|
---|
432 | dtheta = 0;
|
---|
433 | dist = 0;
|
---|
434 | speed = 0;
|
---|
435 | dx = 0;
|
---|
436 | dy = 0;
|
---|
437 | }
|
---|
438 |
|
---|
439 | // Oli's debug statement
|
---|
440 | // if (g1_object_class::selected())
|
---|
441 | // g1_debugxy(0,1,"(%5.2f,%5.2f)-(%5.2f,%6f)",
|
---|
442 | // x, y,
|
---|
443 | // pitch*180/i4_pi(), speed);
|
---|
444 |
|
---|
445 | return (dist==0);
|
---|
446 | }
|
---|
447 |
|
---|
448 | i4_bool g1_player_piece_class::move(i4_float x_amount, i4_float y_amount)
|
---|
449 | {
|
---|
450 | int x1,y1, x2,y2, ix,iy;
|
---|
451 | i4_bool ret = i4_F;
|
---|
452 |
|
---|
453 | if (x_amount==0.0 && y_amount==0.0)
|
---|
454 | return i4_T;
|
---|
455 |
|
---|
456 | i4_3d_vector start, ray(x_amount,y_amount,0), normal, offset, oray;
|
---|
457 | i4_float dist;
|
---|
458 |
|
---|
459 | /*
|
---|
460 | offset = ray;
|
---|
461 | dist = offset.length();
|
---|
462 | offset *= 0.1/dist;
|
---|
463 |
|
---|
464 | ray += offset;
|
---|
465 | */
|
---|
466 |
|
---|
467 | const int nc=8;
|
---|
468 | const i4_float rad = 0.25;
|
---|
469 |
|
---|
470 | for (int i=0; i<nc; i++)
|
---|
471 | {
|
---|
472 | start.set(x+rad*cos(2.0*i4_pi()*(0.5+i)/nc),y+rad*sin(2.0*i4_pi()*(0.5+i)/nc),h+0.07);
|
---|
473 |
|
---|
474 | if (ray.x<0) { x2 = i4_f_to_i(start.x); x1 = i4_f_to_i(start.x+ray.x); }
|
---|
475 | else { x1 = i4_f_to_i(start.x); x2 = i4_f_to_i(start.x+ray.x); }
|
---|
476 | if (ray.y<0) { y2 = i4_f_to_i(start.y); y1 = i4_f_to_i(start.y+ray.y); }
|
---|
477 | else { y1 = i4_f_to_i(start.y); y2 = i4_f_to_i(start.y+ray.y); }
|
---|
478 |
|
---|
479 | for (iy=y1; iy<=y2; iy++)
|
---|
480 | for (ix=x1; ix<=x2; ix++)
|
---|
481 | {
|
---|
482 | g1_object_chain_class *objlist = g1_get_map()->cell(ix,iy)->get_obj_list();
|
---|
483 |
|
---|
484 | while (objlist)
|
---|
485 | {
|
---|
486 | g1_object_class *obj=objlist->object;
|
---|
487 | i4_float dist, dx,dy;
|
---|
488 |
|
---|
489 | if (obj->get_flag(BLOCKING) && obj!=this)
|
---|
490 | {
|
---|
491 | oray = ray;
|
---|
492 | if (g1_model_collide_polygonal(obj, obj->draw_params, start, ray, normal))
|
---|
493 | {
|
---|
494 | if (normal.z>0.8)
|
---|
495 | {
|
---|
496 | // incline more than 45 degrees. let it go
|
---|
497 | ray = oray;
|
---|
498 | }
|
---|
499 | else
|
---|
500 | {
|
---|
501 | // slide perp. to the normal
|
---|
502 | // NOTE: we really should resubmit the new movement vector to objects
|
---|
503 | // in the list we already tried to collide against for more robust
|
---|
504 | // sliding. just hope we catch most of the errors on the next frame
|
---|
505 | i4_3d_vector diff(ray);
|
---|
506 | diff -= oray;
|
---|
507 | normal.z = 0;
|
---|
508 | normal.normalize();
|
---|
509 | normal *= diff.dot(normal) + 0.05;
|
---|
510 | ray = oray;
|
---|
511 | ray += normal;
|
---|
512 | ret = i4_F;
|
---|
513 | }
|
---|
514 | }
|
---|
515 | }
|
---|
516 |
|
---|
517 | objlist = objlist->next_solid();
|
---|
518 | }
|
---|
519 | }
|
---|
520 | }
|
---|
521 |
|
---|
522 | unoccupy_location();
|
---|
523 | /*
|
---|
524 | ray -= offset;
|
---|
525 | */
|
---|
526 | x += ray.x;
|
---|
527 | y += ray.y;
|
---|
528 | if (x<1) x=1; else if (x>g1_get_map()->width()-2) x=g1_get_map()->width()-2;
|
---|
529 | if (y<1) y=1; else if (y>g1_get_map()->height()-2) y=g1_get_map()->height()-2;
|
---|
530 | occupy_location();
|
---|
531 |
|
---|
532 | return ret;
|
---|
533 | }
|
---|
534 |
|
---|
535 | void g1_player_piece_class::lead_target(i4_3d_point_class &lead, int slot_number)
|
---|
536 | {
|
---|
537 | g1_stank_ammo_info_struct *a=ammo+slot_number;
|
---|
538 |
|
---|
539 | int wtype=g1_get_object_type(a->ammo_type->weapon_type);
|
---|
540 | if (wtype)
|
---|
541 | {
|
---|
542 | i4_float shot_speed = g1_object_type_array[wtype]->get_damage_map()->speed;
|
---|
543 | g1_map_piece_class::lead_target(lead,shot_speed);
|
---|
544 | }
|
---|
545 | }
|
---|
546 |
|
---|
547 | void g1_player_piece_class::check_if_turret_in_ground()
|
---|
548 | {
|
---|
549 | if (player_num != g1_player_man.local_player)
|
---|
550 | return;
|
---|
551 |
|
---|
552 | i4_3d_vector pos, dir;
|
---|
553 | float h;
|
---|
554 |
|
---|
555 | do
|
---|
556 | {
|
---|
557 | get_bullet_exit(pos, dir);
|
---|
558 | h=pos.z-g1_get_map()->map_height(pos.x, pos.y, pos.z);
|
---|
559 |
|
---|
560 | if (h<0)
|
---|
561 | turret->rotation.y-=0.01;
|
---|
562 | } while (h<0);
|
---|
563 | }
|
---|
564 |
|
---|
565 |
|
---|
566 | void g1_player_piece_class::check_for_refuel()
|
---|
567 | {
|
---|
568 | g1_object_chain_class *objlist = g1_get_map()->cell(i4_f_to_i(x), i4_f_to_i(y))->get_solid_list();
|
---|
569 | i4_bool on_base=i4_F;
|
---|
570 |
|
---|
571 | while (objlist && !on_base)
|
---|
572 | {
|
---|
573 | g1_object_class *obj=objlist->object;
|
---|
574 | i4_float dist, dx,dy;
|
---|
575 |
|
---|
576 | if (obj->id == main_base_type && obj->player_num==player_num)
|
---|
577 | on_base = i4_T;
|
---|
578 |
|
---|
579 | objlist=objlist->next;
|
---|
580 | }
|
---|
581 |
|
---|
582 | if (on_base)
|
---|
583 | {
|
---|
584 | if (get_stank_flag(g1_player_piece_class::ST_REFUELING)==0)
|
---|
585 | {
|
---|
586 | for (int i=0; i<MAX_WEAPONS; i++)
|
---|
587 | {
|
---|
588 | int mx=ammo[i].ammo_type->max_amount;
|
---|
589 | if (mx==0) mx=1;
|
---|
590 | ammo[i].refuel_delay_remaining=ammo[i].ammo_type->refuel_delay/mx;
|
---|
591 | }
|
---|
592 |
|
---|
593 | set_stank_flag(g1_player_piece_class::ST_REFUELING,1);
|
---|
594 | }
|
---|
595 |
|
---|
596 | health++;
|
---|
597 | if (health>ammo[3].ammo_type->max_amount)
|
---|
598 | {
|
---|
599 | health=ammo[3].ammo_type->max_amount;
|
---|
600 |
|
---|
601 | // if (refuel_sound) sfxfix
|
---|
602 | // if (refuel_sound->is_playing()) refuel_sound->stop();
|
---|
603 | }
|
---|
604 | else
|
---|
605 | {
|
---|
606 | // g1_sound_man.update_dynamic_3d_sound(refuel_sound, sfxfix
|
---|
607 | // i4_3d_vector(x,y,h),
|
---|
608 | // i4_3d_vector(0,0,0),1.0);
|
---|
609 | }
|
---|
610 |
|
---|
611 | for (int i=0; i<MAX_WEAPONS; i++)
|
---|
612 | {
|
---|
613 | if (ammo[i].refuel_delay_remaining)
|
---|
614 | ammo[i].refuel_delay_remaining--;
|
---|
615 | else
|
---|
616 | {
|
---|
617 | if (ammo[i].amount<ammo[i].ammo_type->max_amount)
|
---|
618 | {
|
---|
619 | ammo[i].amount++;
|
---|
620 | // jc:fixme add refuel sfx here
|
---|
621 | }
|
---|
622 |
|
---|
623 | int mx=ammo[i].ammo_type->max_amount;
|
---|
624 | if (mx==0) mx=1;
|
---|
625 | ammo[i].refuel_delay_remaining=ammo[i].ammo_type->refuel_delay/mx;
|
---|
626 | }
|
---|
627 | }
|
---|
628 |
|
---|
629 | }
|
---|
630 | else
|
---|
631 | {
|
---|
632 | if (get_stank_flag(ST_REFUELING))
|
---|
633 | //stop refueling
|
---|
634 | set_stank_flag(ST_REFUELING,0);
|
---|
635 |
|
---|
636 | // if (refuel_sound && refuel_sound->is_playing()) sfxfix
|
---|
637 | // refuel_sound->stop();
|
---|
638 | }
|
---|
639 |
|
---|
640 | }
|
---|
641 |
|
---|
642 | void g1_player_piece_class::set_path(g1_path_handle new_path)
|
---|
643 | {
|
---|
644 | if (path)
|
---|
645 | g1_path_manager.free_path(path);
|
---|
646 | path=new_path;
|
---|
647 | }
|
---|
648 |
|
---|
649 | i4_bool g1_player_piece_class::deploy_to(float destx, float desty)
|
---|
650 | {
|
---|
651 | i4_float points[200];
|
---|
652 | w16 t_points;
|
---|
653 | g1_path_handle ph=0;
|
---|
654 |
|
---|
655 | if (g1_get_map()->find_path(x,y, destx,desty, points,t_points) && t_points>1)
|
---|
656 | ph=g1_path_manager.alloc_path(t_points-1, points);
|
---|
657 |
|
---|
658 | set_path(ph);
|
---|
659 |
|
---|
660 | return (ph!=0);
|
---|
661 | }
|
---|
662 |
|
---|
663 | w32 g1_player_piece_class::follow_path()
|
---|
664 | {
|
---|
665 | if (!path) return NO_PATH;
|
---|
666 |
|
---|
667 | g1_path_manager.get_position(path, dest_x, dest_y);
|
---|
668 |
|
---|
669 | // first check to see if we're already there
|
---|
670 | i4_float dx = (x-dest_x), dy = (y-dest_y);
|
---|
671 | i4_float dist = dx*dx+dy*dy;
|
---|
672 |
|
---|
673 | //if we're there, advance to the next path position
|
---|
674 | if (dist<=0.01)
|
---|
675 | {
|
---|
676 | path = g1_path_manager.advance_path(path);
|
---|
677 | if (!path) return NO_PATH;
|
---|
678 |
|
---|
679 | g1_path_manager.get_position(path, dest_x, dest_y);
|
---|
680 | }
|
---|
681 | return (g1_path_manager.is_last_path_point(path))? FINAL_POINT : GAME_PATH;
|
---|
682 | }
|
---|
683 |
|
---|
684 | void g1_player_piece_class::check_for_powerups()
|
---|
685 | {
|
---|
686 | i4_3d_vector v=i4_3d_vector(x,y,h);
|
---|
687 | float r=2.0;
|
---|
688 |
|
---|
689 | int fog_rect_x1=10000, fog_rect_y1=10000,
|
---|
690 | fog_rect_x2=-1, fog_rect_y2=-1, ix,iy;
|
---|
691 |
|
---|
692 | g1_map_class *map=g1_get_map();
|
---|
693 |
|
---|
694 | int x_left = i4_f_to_i(v.x-r); if (x_left<0) x_left=0;
|
---|
695 | int x_right = i4_f_to_i(v.x+r); if (x_right>=map->width()) x_right=map->width()-1;
|
---|
696 | int y_top = i4_f_to_i(v.y-r); if (y_top<0) y_top=0;
|
---|
697 | int y_bottom = i4_f_to_i(v.y+r); if (y_bottom>=map->height()) y_bottom=map->height()-1;
|
---|
698 |
|
---|
699 | for (iy=y_top; iy<=y_bottom; iy++)
|
---|
700 | {
|
---|
701 | g1_map_cell_class *c=map->cell(x_left,iy);
|
---|
702 | for (ix=x_left; ix<=x_right; ix++, c++)
|
---|
703 | {
|
---|
704 | for (g1_object_chain_class *o=c->get_obj_list(); o; o=o->next)
|
---|
705 | {
|
---|
706 | g1_object_class *obj=o->object;
|
---|
707 | if (!obj->get_flag(g1_object_class::SCRATCH_BIT))
|
---|
708 | {
|
---|
709 | obj->set_flag(g1_object_class::SCRATCH_BIT, 1);
|
---|
710 | obj->note_stank_near(this);
|
---|
711 | }
|
---|
712 | }
|
---|
713 | }
|
---|
714 | }
|
---|
715 |
|
---|
716 |
|
---|
717 | for (iy=y_top; iy<=y_bottom; iy++)
|
---|
718 | {
|
---|
719 | g1_map_cell_class *c=map->cell(x_left,iy);
|
---|
720 | for (ix=x_left; ix<=x_right; ix++, c++)
|
---|
721 | for (g1_object_chain_class *o=c->get_obj_list(); o; o=o->next)
|
---|
722 | o->object->set_flag(g1_object_class::SCRATCH_BIT, 0);
|
---|
723 | }
|
---|
724 | }
|
---|
725 |
|
---|
726 |
|
---|
727 | void g1_player_piece_class::think()
|
---|
728 | {
|
---|
729 | pf_stank_think.start();
|
---|
730 |
|
---|
731 | // Save old values of position & orientation
|
---|
732 | lbase_angle = base_angle;
|
---|
733 | lturret_kick = turret_kick;
|
---|
734 |
|
---|
735 | if (!check_life())
|
---|
736 | {
|
---|
737 | // g1_sound_man.play(STATIC_3D_SOUND,g1_sfx_explosion_ground_vehicle,i4_3d_vector(x,y,h)); sfxfix
|
---|
738 |
|
---|
739 | // if (refuel_sound) sfxfix
|
---|
740 | // {
|
---|
741 | // g1_sound_man.free_dynamic_3d_sound(refuel_sound);
|
---|
742 | // refuel_sound=0;
|
---|
743 | // }
|
---|
744 | supertank_lost.play();
|
---|
745 | pf_stank_think.stop();
|
---|
746 | return;
|
---|
747 | }
|
---|
748 |
|
---|
749 | check_for_refuel();
|
---|
750 | check_for_powerups();
|
---|
751 |
|
---|
752 | i4_bool process_input = i4_T;
|
---|
753 |
|
---|
754 | w32 pathinfo = follow_path();
|
---|
755 |
|
---|
756 | if (player_num==g1_human->team() &&
|
---|
757 | (!g1_current_controller.get() ||
|
---|
758 | (g1_current_controller->view.get_view_mode()!=G1_ACTION_MODE) &&
|
---|
759 | g1_current_controller->view.get_view_mode()!=G1_FOLLOW_MODE &&
|
---|
760 | g1_current_controller->view.get_view_mode()!=G1_WATCH_MODE
|
---|
761 | ))
|
---|
762 | process_input = i4_F;
|
---|
763 |
|
---|
764 | // Process real user movement
|
---|
765 |
|
---|
766 | // User Input
|
---|
767 | if (process_input)
|
---|
768 | {
|
---|
769 | // Process mouse movement for looking around
|
---|
770 | i4_normalize_angle(mouse_look_increment_x);
|
---|
771 |
|
---|
772 | mouse_look_x -= mouse_look_increment_x;
|
---|
773 | i4_normalize_angle(mouse_look_x);
|
---|
774 | base_angle -= mouse_look_increment_x;
|
---|
775 | i4_normalize_angle(base_angle);
|
---|
776 |
|
---|
777 | if (mouse_look_increment_y!=0)
|
---|
778 | mouse_look_y = turret->rotation.y;
|
---|
779 |
|
---|
780 | mouse_look_y += mouse_look_increment_y;
|
---|
781 | i4_normalize_angle(mouse_look_y);
|
---|
782 |
|
---|
783 | if (mouse_look_y < 3*i4_pi()/2 && mouse_look_y > i4_pi()/2)
|
---|
784 | {
|
---|
785 | if (mouse_look_increment_y>0)
|
---|
786 | mouse_look_y = i4_pi()/2;
|
---|
787 | else
|
---|
788 | mouse_look_y = 3*i4_pi()/2;
|
---|
789 | }
|
---|
790 | }
|
---|
791 |
|
---|
792 | mouse_look_increment_x = 0;
|
---|
793 | mouse_look_increment_y = 0;
|
---|
794 |
|
---|
795 | // Movement
|
---|
796 | if (pathinfo)
|
---|
797 | {
|
---|
798 | // Move along the set path
|
---|
799 | i4_float dist, dtheta, dx, dy, brakes=0.0;
|
---|
800 |
|
---|
801 | if (pathinfo==FINAL_POINT)
|
---|
802 | brakes=0.1;
|
---|
803 |
|
---|
804 | suggest_move(dist, dtheta, dx, dy, brakes);
|
---|
805 | move(dx,dy);
|
---|
806 |
|
---|
807 | if (speed*speed>=dist)
|
---|
808 | {
|
---|
809 | i4_3d_vector a,b,c;
|
---|
810 |
|
---|
811 | path = g1_path_manager.advance_path(path);
|
---|
812 |
|
---|
813 | a.set(x,y,0);
|
---|
814 | b.z=c.z=0;
|
---|
815 | if (g1_path_manager.get_nth_position(path,0,b.x,b.y) &&
|
---|
816 | g1_path_manager.get_nth_position(path,1,c.x,c.y))
|
---|
817 | {
|
---|
818 | c -= b;
|
---|
819 | b -= a;
|
---|
820 | b.normalize();
|
---|
821 | c.normalize();
|
---|
822 | brakes = (b.dot(c)<0.8) ? 0.1 : 0.0;
|
---|
823 | }
|
---|
824 | }
|
---|
825 |
|
---|
826 | if (!process_input)
|
---|
827 | base_angle = theta;
|
---|
828 |
|
---|
829 | g1_add_to_sound_average(G1_RUMBLE_STANK, i4_3d_vector(x,y,h), i4_3d_vector(x-lx, y-ly, h-lh));
|
---|
830 | }
|
---|
831 | else
|
---|
832 | {
|
---|
833 | i4_angle desired_base = base_angle;
|
---|
834 |
|
---|
835 | if (process_input)
|
---|
836 | {
|
---|
837 | // process turning
|
---|
838 | base_angle += dtheta;
|
---|
839 | i4_normalize_angle(base_angle);
|
---|
840 | }
|
---|
841 |
|
---|
842 | if (process_input && !get_stank_flag(ST_INFLIGHT))
|
---|
843 | {
|
---|
844 | if (accel_ratio)
|
---|
845 | {
|
---|
846 | // process acceleration
|
---|
847 | if (!get_stank_flag(ST_SLIDING))
|
---|
848 | speed += defaults->accel*accel_ratio;
|
---|
849 | speed += sin(pitch)*g1_resources.gravity;
|
---|
850 | speed -= speed*damping_fraction;
|
---|
851 | }
|
---|
852 |
|
---|
853 | if (strafe_accel_ratio)
|
---|
854 | {
|
---|
855 | // do strafing
|
---|
856 | strafe_speed += g1_resources.player_accel * strafe_accel_ratio;
|
---|
857 | strafe_speed -= strafe_speed*damping_fraction;
|
---|
858 | }
|
---|
859 |
|
---|
860 | desired_base = base_angle;
|
---|
861 | if (strafe_accel_ratio<0)
|
---|
862 | {
|
---|
863 | if (accel_ratio<0) desired_base = 3*i4_pi()/4+base_angle;
|
---|
864 | else if (accel_ratio>0) desired_base=i4_pi()/4+base_angle;
|
---|
865 | else desired_base=i4_pi()/2+base_angle;
|
---|
866 |
|
---|
867 | i4_normalize_angle(desired_base);
|
---|
868 | }
|
---|
869 | else if (strafe_accel_ratio>0)
|
---|
870 | {
|
---|
871 | if (accel_ratio<0) desired_base=5*i4_pi()/4+base_angle;
|
---|
872 | else if (accel_ratio>0) desired_base=7*i4_pi()/4+base_angle;
|
---|
873 | else desired_base=3*i4_pi()/2+base_angle;
|
---|
874 |
|
---|
875 | i4_normalize_angle(desired_base);
|
---|
876 | }
|
---|
877 | }
|
---|
878 |
|
---|
879 | if (!get_stank_flag(ST_INFLIGHT))
|
---|
880 | {
|
---|
881 | // Process braking
|
---|
882 | if (accel_ratio==0)
|
---|
883 | {
|
---|
884 | speed = speed*g1_resources.player_stop_friction;
|
---|
885 | if (speed<0.01 && speed>-0.01)
|
---|
886 | speed=0;
|
---|
887 | }
|
---|
888 | if (strafe_accel_ratio==0)
|
---|
889 | {
|
---|
890 | strafe_speed = strafe_speed*g1_resources.player_stop_friction;
|
---|
891 | if (strafe_speed<0.01 && strafe_speed>-0.01)
|
---|
892 | strafe_speed=0;
|
---|
893 | }
|
---|
894 | }
|
---|
895 |
|
---|
896 | dtheta=0;
|
---|
897 | accel_ratio=0;
|
---|
898 | strafe_accel_ratio=0;
|
---|
899 |
|
---|
900 | // Do desired rotation
|
---|
901 | i4_rotate_to(theta,desired_base,g1_resources.player_turn_speed+0.1);
|
---|
902 |
|
---|
903 | // Move me
|
---|
904 | i4_float
|
---|
905 | mv_speed = cos(groundpitch)*speed,
|
---|
906 | mv_strafe_speed = cos(groundroll)*strafe_speed;
|
---|
907 |
|
---|
908 | i4_float
|
---|
909 | dx = cos(base_angle)*mv_speed + cos(base_angle-i4_pi()/2)*mv_strafe_speed,
|
---|
910 | dy = sin(base_angle)*mv_speed + sin(base_angle-i4_pi()/2)*mv_strafe_speed;
|
---|
911 |
|
---|
912 | #if 0
|
---|
913 | if (groundpitch<-0.5 || groundpitch>0.5 || groundroll<-0.5 || groundroll>0.5)
|
---|
914 | {
|
---|
915 | dx += sin(groundpitch)*g1_resources.gravity;
|
---|
916 | dy -= sin(groundroll)*g1_resources.gravity;
|
---|
917 | set_stank_flag(ST_SLIDING,1);
|
---|
918 | }
|
---|
919 | else
|
---|
920 | set_stank_flag(ST_SLIDING,0);
|
---|
921 | #endif
|
---|
922 |
|
---|
923 | move(dx,dy);
|
---|
924 |
|
---|
925 | if (turret->h != cur_top_attach)
|
---|
926 | turret->h = cur_top_attach;
|
---|
927 |
|
---|
928 | }
|
---|
929 |
|
---|
930 | switch ((int)(base_angle*8/(2*i4_pi())))
|
---|
931 | {
|
---|
932 | case 0 : radar_image=&radar_im0; break;
|
---|
933 | case 1 : radar_image=&radar_im2; break;
|
---|
934 | case 2 : radar_image=&radar_im4; break;
|
---|
935 | case 3 : radar_image=&radar_im6; break;
|
---|
936 | case 4 : radar_image=&radar_im8; break;
|
---|
937 | case 5 : radar_image=&radar_im10; break;
|
---|
938 | case 6 : radar_image=&radar_im12; break;
|
---|
939 | case 7 : radar_image=&radar_im14; break;
|
---|
940 | }
|
---|
941 |
|
---|
942 |
|
---|
943 |
|
---|
944 | // Calculate height physics & pitch & roll
|
---|
945 |
|
---|
946 | i4_float newground = g1_get_map()->map_height(x,y,lh);
|
---|
947 |
|
---|
948 | if (h-0.00001+vspeed > newground)
|
---|
949 | {
|
---|
950 | //he's off the ground
|
---|
951 | //dont set these to 0, just leave them the way they were
|
---|
952 | groundpitch = lgroundpitch;
|
---|
953 | groundroll = lgroundroll;
|
---|
954 |
|
---|
955 | h += vspeed;
|
---|
956 | vspeed -= g1_resources.gravity;
|
---|
957 |
|
---|
958 | set_stank_flag(ST_INFLIGHT);
|
---|
959 | }
|
---|
960 | else
|
---|
961 | {
|
---|
962 | // steady on the ground
|
---|
963 |
|
---|
964 | vspeed = newground - h - g1_resources.gravity;
|
---|
965 |
|
---|
966 | h = newground;
|
---|
967 |
|
---|
968 | i4_3d_vector z2, z3;
|
---|
969 |
|
---|
970 | z2.set(x+0.1, y, 0);
|
---|
971 | z3.set(x-0.1, y, 0);
|
---|
972 | z2.z = g1_get_map()->map_height(z2.x,z2.y,lh);
|
---|
973 | z3.z = g1_get_map()->map_height(z3.x,z3.y,lh);
|
---|
974 | groundpitch = -i4_atan2(z2.z - z3.z,0.5);
|
---|
975 |
|
---|
976 | z2.set(x, y+0.1, 0);
|
---|
977 | z3.set(x, y-0.1, 0);
|
---|
978 | z2.z = g1_get_map()->map_height(z2.x,z2.y,lh);
|
---|
979 | z3.z = g1_get_map()->map_height(z3.x,z3.y,lh);
|
---|
980 | groundroll = i4_atan2(z2.z - z3.z,0.5);
|
---|
981 |
|
---|
982 | pitch = 0;
|
---|
983 |
|
---|
984 | if (player_num != g1_player_man.local_player)
|
---|
985 | roll = 0;
|
---|
986 | else
|
---|
987 | roll = 0.8*roll;
|
---|
988 |
|
---|
989 | set_stank_flag(ST_INFLIGHT,0);
|
---|
990 | }
|
---|
991 |
|
---|
992 | if (hurt>0.0)
|
---|
993 | {
|
---|
994 | g1_hurt_tint = i4_f_to_i((G1_NUM_HURT_TINTS-1)*hurt)+1;
|
---|
995 | hurt-=0.05;
|
---|
996 | if (hurt<0.0)
|
---|
997 | hurt = 0.0;
|
---|
998 | }
|
---|
999 | else
|
---|
1000 | g1_hurt_tint = 0;
|
---|
1001 |
|
---|
1002 | if (vspeed>0.3) // don't jump too high
|
---|
1003 | vspeed=0.3;
|
---|
1004 |
|
---|
1005 | // Orient turrent
|
---|
1006 | if (process_input)
|
---|
1007 | {
|
---|
1008 | turret->rotation.x = 0;
|
---|
1009 | turret->rotation.y = mouse_look_y;
|
---|
1010 | turret->rotation.z = base_angle;
|
---|
1011 |
|
---|
1012 | check_if_turret_in_ground();
|
---|
1013 | }
|
---|
1014 | else
|
---|
1015 | {
|
---|
1016 | turret->rotation.x = 0;
|
---|
1017 | turret->rotation.y = turret->lrotation.y = 0;
|
---|
1018 | turret->rotation.x = turret->lrotation.x = 0;
|
---|
1019 | }
|
---|
1020 |
|
---|
1021 | // Do firing stuff
|
---|
1022 | if (turret_kick < 0.f)
|
---|
1023 | turret_kick += 0.02;
|
---|
1024 |
|
---|
1025 | // Update delays
|
---|
1026 | for (int del=0; del<MAX_WEAPONS; del++)
|
---|
1027 | if (ammo[del].delay_remaining)
|
---|
1028 | ammo[del].delay_remaining--;
|
---|
1029 |
|
---|
1030 | look_for_targets();
|
---|
1031 |
|
---|
1032 |
|
---|
1033 | if (player_num!=g1_player_man.local_player)
|
---|
1034 | find_target();
|
---|
1035 | else
|
---|
1036 | g1_unfog_radius(i4_3d_vector(x,y,h), 10.0);
|
---|
1037 |
|
---|
1038 | if (process_input)
|
---|
1039 | {
|
---|
1040 | for (int i=0; i<MAX_WEAPONS-1; i++)
|
---|
1041 | if (fire[i])
|
---|
1042 | {
|
---|
1043 | fire[i]=0;
|
---|
1044 | fire_weapon(i);
|
---|
1045 | }
|
---|
1046 | }
|
---|
1047 | else
|
---|
1048 | {
|
---|
1049 | // Auto-fire
|
---|
1050 | if (attack_target.valid())
|
---|
1051 | {
|
---|
1052 | g1_object_class *mp = attack_target.get();
|
---|
1053 |
|
---|
1054 | i4_float dx,dy,angle, dangle;
|
---|
1055 |
|
---|
1056 | //this will obviously only be true if attack_target.ref != NULL
|
---|
1057 | dx = (mp->x - (x+turret->x));
|
---|
1058 | dy = (mp->y - (y+turret->y));
|
---|
1059 |
|
---|
1060 | //aim the turret
|
---|
1061 |
|
---|
1062 | angle = i4_atan2(dy,dx);
|
---|
1063 |
|
---|
1064 | //snap it
|
---|
1065 | i4_normalize_angle(angle);
|
---|
1066 |
|
---|
1067 | dangle = i4_rotate_to(turret->rotation.z, angle, defaults->turn_speed);
|
---|
1068 | if (dangle<defaults->turn_speed && dangle>-defaults->turn_speed)
|
---|
1069 | fire_weapon(2);
|
---|
1070 | }
|
---|
1071 | else
|
---|
1072 | {
|
---|
1073 | if (!moved())
|
---|
1074 | {
|
---|
1075 | if (g1_tick_counter & 128)
|
---|
1076 | turret->rotation.z +=
|
---|
1077 | defaults->turn_speed * sin(i4_2pi() * (float)(g1_tick_counter & 63) / 64.f);
|
---|
1078 | else
|
---|
1079 | turret->rotation.z -=
|
---|
1080 | defaults->turn_speed * sin(i4_2pi() * (float)(g1_tick_counter & 63) / 64.f);
|
---|
1081 | }
|
---|
1082 | }
|
---|
1083 | }
|
---|
1084 |
|
---|
1085 | request_think();
|
---|
1086 |
|
---|
1087 | pf_stank_think.stop();
|
---|
1088 | }
|
---|
1089 |
|
---|
1090 |
|
---|
1091 | void g1_player_piece_class::track_base(i4_float desired_angle)
|
---|
1092 | {
|
---|
1093 | i4_float d;
|
---|
1094 |
|
---|
1095 | d = i4_angle_diff(desired_angle, theta);
|
---|
1096 |
|
---|
1097 | if (d<g1_resources.strafe_turn_speed)
|
---|
1098 | {
|
---|
1099 | theta=desired_angle;
|
---|
1100 | return ;
|
---|
1101 | }
|
---|
1102 |
|
---|
1103 | if (i4_angle_minus(desired_angle, theta) < i4_pi())
|
---|
1104 | {
|
---|
1105 | theta += g1_resources.strafe_turn_speed;
|
---|
1106 | if (theta>=i4_2pi()) theta-=i4_2pi();
|
---|
1107 | }
|
---|
1108 | else
|
---|
1109 | {
|
---|
1110 | theta -= g1_resources.strafe_turn_speed;
|
---|
1111 | if (theta<0)
|
---|
1112 | theta += i4_2pi();
|
---|
1113 | }
|
---|
1114 | }
|
---|
1115 |
|
---|
1116 |
|
---|
1117 | extern w32 g1_num_objs_in_view;
|
---|
1118 | extern w32 g1_objs_in_view[];
|
---|
1119 |
|
---|
1120 | g1_object_class *g1_player_piece_class::find_view_target(const i4_3d_vector &view_pos,
|
---|
1121 | const i4_3d_vector &view_dir,
|
---|
1122 | find_view_type type,
|
---|
1123 | float max_dist)
|
---|
1124 | {
|
---|
1125 | sw32 i;
|
---|
1126 | i4_float best;
|
---|
1127 | i4_3d_vector vdir=view_dir;
|
---|
1128 | vdir.normalize();
|
---|
1129 |
|
---|
1130 |
|
---|
1131 | if (type==USE_SLOP)
|
---|
1132 | best = cos(i4_deg2rad(g1_resources.player_fire_slop_angle));
|
---|
1133 | else
|
---|
1134 | best = 0.0;
|
---|
1135 |
|
---|
1136 | g1_object_class *fire_at_this = 0;
|
---|
1137 |
|
---|
1138 | if (g1_num_objs_in_view <= 0) return 0;
|
---|
1139 |
|
---|
1140 | for (i=0;i<g1_num_objs_in_view;i++)
|
---|
1141 | {
|
---|
1142 | if (g1_global_id.check_id(g1_objs_in_view[i]))
|
---|
1143 | {
|
---|
1144 | g1_object_class *p = g1_global_id.get(g1_objs_in_view[i]);
|
---|
1145 |
|
---|
1146 | if (p && can_attack(p) && p->get_flag(DANGEROUS) && p!=(g1_object_class *)this)
|
---|
1147 | {
|
---|
1148 | i4_3d_vector source_to_target = i4_3d_vector(p->x, p->y, p->h);
|
---|
1149 | source_to_target -= view_pos;
|
---|
1150 |
|
---|
1151 | float dist=source_to_target.length();
|
---|
1152 | source_to_target/=dist;
|
---|
1153 |
|
---|
1154 | i4_float dot = fabs(source_to_target.dot(vdir));
|
---|
1155 | if (dot > best && dist<max_dist)
|
---|
1156 | {
|
---|
1157 | best = dot;
|
---|
1158 | fire_at_this = p;
|
---|
1159 | }
|
---|
1160 | }
|
---|
1161 | }
|
---|
1162 | }
|
---|
1163 |
|
---|
1164 | return fire_at_this;
|
---|
1165 | }
|
---|
1166 |
|
---|
1167 |
|
---|
1168 | i4_bool g1_player_piece_class::in_range(int slot_number, g1_object_class *o) const
|
---|
1169 | {
|
---|
1170 | if (!o) return i4_F;
|
---|
1171 |
|
---|
1172 | int wtype=g1_get_object_type(ammo[slot_number].ammo_type->weapon_type);
|
---|
1173 | if (wtype==0) return i4_F;
|
---|
1174 |
|
---|
1175 | i4_float range=g1_object_type_array[wtype]->get_damage_map()->range;
|
---|
1176 | range *= range;
|
---|
1177 | i4_float dist = (o->x-x)*(o->x-x) + (o->y-y)*(o->y-y);
|
---|
1178 |
|
---|
1179 | return dist<range;
|
---|
1180 | }
|
---|
1181 |
|
---|
1182 | i4_bool g1_player_piece_class::fire_weapon(int slot_number)
|
---|
1183 | {
|
---|
1184 | g1_stank_ammo_info_struct *a=ammo+slot_number;
|
---|
1185 | if (a->delay_remaining)
|
---|
1186 | a->delay_remaining--;
|
---|
1187 | else
|
---|
1188 | {
|
---|
1189 | if (a->amount)
|
---|
1190 | {
|
---|
1191 | i4_3d_point_class bpos, bdir;
|
---|
1192 | get_bullet_exit(bpos, bdir);
|
---|
1193 |
|
---|
1194 | float range=0;
|
---|
1195 | int wtype=g1_get_object_type(a->ammo_type->weapon_type);
|
---|
1196 | if (wtype)
|
---|
1197 | range=g1_object_type_array[wtype]->get_damage_map()->range;
|
---|
1198 |
|
---|
1199 | g1_object_class *fire_at=a->current_target.get();
|
---|
1200 |
|
---|
1201 | #if 0
|
---|
1202 | if (!fire_at)
|
---|
1203 | fire_at = attack_target.get();
|
---|
1204 | #endif
|
---|
1205 |
|
---|
1206 | // adjust fire direction to point directly at the object
|
---|
1207 | if (fire_at)
|
---|
1208 | {
|
---|
1209 | i4_3d_vector lead;
|
---|
1210 |
|
---|
1211 | attack_target = a->current_target.get();
|
---|
1212 | lead_target(bdir, slot_number);
|
---|
1213 | bdir -= bpos;
|
---|
1214 | bdir.z += fire_at->occupancy_radius()/3;
|
---|
1215 | }
|
---|
1216 |
|
---|
1217 | g1_object_class *weapon = g1_fire(a->ammo_type->weapon_type, this,
|
---|
1218 | fire_at,
|
---|
1219 | bpos,
|
---|
1220 | bdir,
|
---|
1221 | a->last_fired_object.get());
|
---|
1222 | if (weapon)
|
---|
1223 | {
|
---|
1224 | a->amount--;
|
---|
1225 | a->delay_remaining=a->ammo_type->fire_delay;
|
---|
1226 | a->last_fired_object = weapon;
|
---|
1227 | }
|
---|
1228 |
|
---|
1229 | return i4_T;
|
---|
1230 | }
|
---|
1231 | }
|
---|
1232 |
|
---|
1233 | return i4_F;
|
---|
1234 | }
|
---|
1235 |
|
---|
1236 |
|
---|
1237 |
|
---|
1238 | void fast_transform(i4_transform_class *t,const i4_3d_vector &src, r1_3d_point_class &dst);
|
---|
1239 |
|
---|
1240 |
|
---|
1241 | static r1_texture_ref target_cursor_sprite("target_cursor");
|
---|
1242 | static r1_texture_ref target_gun_cursor_sprite("gun_target_cursor");
|
---|
1243 | static g1_model_ref lock_on("lock_on"), lock_on_guns("lock_on_guns");
|
---|
1244 |
|
---|
1245 |
|
---|
1246 | static void draw_spining_tris(float px, float py, float z,
|
---|
1247 | float theta,
|
---|
1248 | g1_quad_object_class *o,
|
---|
1249 | int ticks)
|
---|
1250 | {
|
---|
1251 | g1_vert_class *v=o->get_verts(0,0);
|
---|
1252 |
|
---|
1253 | i4_transform_class t;
|
---|
1254 | t.identity();
|
---|
1255 | t.mult_translate(px,py,0);
|
---|
1256 |
|
---|
1257 | float s=g1_render.center_x / z;
|
---|
1258 |
|
---|
1259 | if (ticks<10)
|
---|
1260 | {
|
---|
1261 | ticks=11-ticks;
|
---|
1262 | while (ticks--)
|
---|
1263 | s*=1.1;
|
---|
1264 | }
|
---|
1265 |
|
---|
1266 | t.mult_scale(s,s,1);
|
---|
1267 | t.mult_rotate_z(theta);
|
---|
1268 | t.mult_rotate_x(i4_pi()/2.0);
|
---|
1269 |
|
---|
1270 |
|
---|
1271 |
|
---|
1272 | r1_render_api_class *api=g1_render.r_api;
|
---|
1273 |
|
---|
1274 |
|
---|
1275 | r1_vert tv[4];
|
---|
1276 | for (int k=0; k<4; k++)
|
---|
1277 | {
|
---|
1278 | tv[k].v.z=r1_near_clip_z;
|
---|
1279 | tv[k].a=1;
|
---|
1280 | tv[k].w=r1_ooz(tv[k].v.z);
|
---|
1281 | tv[k].r=1;
|
---|
1282 | tv[k].g=1;
|
---|
1283 | tv[k].b=1;
|
---|
1284 | }
|
---|
1285 |
|
---|
1286 | for (int i=0; i<o->num_quad; i++)
|
---|
1287 | {
|
---|
1288 | i4_bool off=i4_F;
|
---|
1289 |
|
---|
1290 | g1_quad_class *q=o->quad+i;
|
---|
1291 | int t_verts=q->num_verts();
|
---|
1292 | for (int j=0; j<t_verts; j++)
|
---|
1293 | {
|
---|
1294 | t.transform(v[q->vertex_ref[j]].v, tv[j].v);
|
---|
1295 | tv[j].px=tv[j].v.x;
|
---|
1296 | tv[j].py=tv[j].v.y;
|
---|
1297 |
|
---|
1298 | if (tv[j].v.x<0 || tv[j].v.x>g1_render.center_x*2 ||
|
---|
1299 | tv[j].v.y<0 || tv[j].v.y>g1_render.center_y*2)
|
---|
1300 | off=i4_T;
|
---|
1301 | }
|
---|
1302 |
|
---|
1303 | if (!off)
|
---|
1304 | {
|
---|
1305 | g1_render.r_api->use_texture(q->material_ref, 8, 0);
|
---|
1306 | g1_render.r_api->render_poly(t_verts, tv);
|
---|
1307 | }
|
---|
1308 | }
|
---|
1309 | }
|
---|
1310 |
|
---|
1311 |
|
---|
1312 | void g1_player_piece_class::draw_target_cursors(g1_draw_context_class *context)
|
---|
1313 | {
|
---|
1314 | float z=r1_near_clip_z;
|
---|
1315 | float w_mult=z/g1_render.center_x;
|
---|
1316 |
|
---|
1317 | g1_render.render_sprite(i4_3d_vector(0,0,z),
|
---|
1318 | target_cursor_sprite.get(), 33 * w_mult, 33 * w_mult);
|
---|
1319 |
|
---|
1320 | r1_vert v;
|
---|
1321 |
|
---|
1322 | float theta=(g1_tick_counter + g1_render.frame_ratio)/4.0;
|
---|
1323 |
|
---|
1324 | if (ammo[1].current_target.get())
|
---|
1325 | {
|
---|
1326 | g1_object_class *t=ammo[1].current_target.get();
|
---|
1327 | i4_3d_vector p=i4_3d_vector(t->x, t->y, t->h+ t->occupancy_radius()/3.0);
|
---|
1328 | i4_3d_vector lp=i4_3d_vector(t->lx, t->ly, t->lh+ t->occupancy_radius()/3.0);
|
---|
1329 | i4_3d_vector ip;
|
---|
1330 | ip.interpolate(lp, p, g1_render.frame_ratio);
|
---|
1331 |
|
---|
1332 | if (g1_render.project_point(ip, v, context->transform))
|
---|
1333 | draw_spining_tris(v.px, v.py, v.v.z, theta,
|
---|
1334 | lock_on_guns.get(),
|
---|
1335 | ammo[1].ticks_this_has_been_my_current_target);
|
---|
1336 | }
|
---|
1337 |
|
---|
1338 | theta+=0.4;
|
---|
1339 | if (ammo[2].current_target.get())
|
---|
1340 | {
|
---|
1341 | g1_object_class *t=ammo[2].current_target.get();
|
---|
1342 |
|
---|
1343 | i4_3d_vector p=i4_3d_vector(t->x, t->y, t->h+ t->occupancy_radius()/3.0);
|
---|
1344 | i4_3d_vector lp=i4_3d_vector(t->lx, t->ly, t->lh+ t->occupancy_radius()/3.0);
|
---|
1345 | i4_3d_vector ip;
|
---|
1346 | ip.interpolate(lp, p, g1_render.frame_ratio);
|
---|
1347 |
|
---|
1348 | if (g1_render.project_point(ip, v, context->transform))
|
---|
1349 | draw_spining_tris(v.px, v.py, v.v.z, theta,
|
---|
1350 | lock_on.get(),
|
---|
1351 | ammo[1].ticks_this_has_been_my_current_target);
|
---|
1352 | }
|
---|
1353 |
|
---|
1354 | }
|
---|
1355 |
|
---|
1356 | void g1_player_piece_class::look_for_targets()
|
---|
1357 | {
|
---|
1358 | if (!g1_player_man.get_local() ||
|
---|
1359 | g1_player_man.get_local()->get_player_num()!=player_num)
|
---|
1360 | {
|
---|
1361 | ammo[0].current_target=0;
|
---|
1362 | if (attack_target.valid())
|
---|
1363 | ammo[1].current_target = attack_target.get();
|
---|
1364 | ammo[2].current_target=0;
|
---|
1365 | return;
|
---|
1366 | }
|
---|
1367 |
|
---|
1368 | i4_3d_vector bpos, bdir;
|
---|
1369 | get_bullet_exit(bpos, bdir);
|
---|
1370 |
|
---|
1371 | for (int i=0; i<MAX_WEAPONS; i++)
|
---|
1372 | {
|
---|
1373 | if (ammo[i].amount)
|
---|
1374 | {
|
---|
1375 | float range=0;
|
---|
1376 | int wtype=g1_get_object_type(ammo[i].ammo_type->weapon_type);
|
---|
1377 | if (wtype)
|
---|
1378 | range=g1_object_type_array[wtype]->get_damage_map()->range;
|
---|
1379 |
|
---|
1380 | g1_object_class *t=find_view_target(bpos, bdir, i ? USE_SCREEN : USE_SLOP, range);
|
---|
1381 |
|
---|
1382 | if (t==ammo[i].current_target.get())
|
---|
1383 | ammo[i].ticks_this_has_been_my_current_target++;
|
---|
1384 | else
|
---|
1385 | {
|
---|
1386 | ammo[i].ticks_this_has_been_my_current_target=0;
|
---|
1387 | ammo[i].current_target=t;
|
---|
1388 | }
|
---|
1389 | }
|
---|
1390 | else
|
---|
1391 | {
|
---|
1392 | ammo[i].ticks_this_has_been_my_current_target=0;
|
---|
1393 | ammo[i].current_target=0;
|
---|
1394 | }
|
---|
1395 | }
|
---|
1396 | }
|
---|
1397 |
|
---|
1398 | void g1_player_piece_class::draw(g1_draw_context_class *context)
|
---|
1399 | {
|
---|
1400 | g1_player_piece_class *local_stank=g1_player_man.get_local()->get_commander();
|
---|
1401 |
|
---|
1402 |
|
---|
1403 | if (g1_current_controller.get() &&
|
---|
1404 | this==local_stank && g1_current_controller->view.get_view_mode()==G1_ACTION_MODE)
|
---|
1405 | draw_target_cursors(context);
|
---|
1406 |
|
---|
1407 |
|
---|
1408 | sw8 damage_level;
|
---|
1409 |
|
---|
1410 | if (health > defaults->health)
|
---|
1411 | damage_level = 7;
|
---|
1412 | else
|
---|
1413 | if (health < 0)
|
---|
1414 | damage_level = 0;
|
---|
1415 | else
|
---|
1416 | damage_level = i4_f_to_i(7.f * health / (float)defaults->health);
|
---|
1417 |
|
---|
1418 | g1_render.set_render_damage_level(damage_level);
|
---|
1419 |
|
---|
1420 | g1_screen_box *bbox=0;
|
---|
1421 |
|
---|
1422 | if (get_flag(g1_object_class::SELECTABLE | g1_object_class::TARGETABLE))
|
---|
1423 | {
|
---|
1424 | if (g1_render.current_selectable_list)
|
---|
1425 | bbox=g1_render.current_selectable_list->add();
|
---|
1426 | if (bbox)
|
---|
1427 | {
|
---|
1428 | bbox->x1 = 2048;
|
---|
1429 | bbox->y1 = 2048;
|
---|
1430 | bbox->x2 = -1;
|
---|
1431 | bbox->y2 = -1;
|
---|
1432 | bbox->z1 = 999999;
|
---|
1433 | bbox->z2 = -999999;
|
---|
1434 | bbox->w = 1.0/999999;
|
---|
1435 | bbox->object_id=global_id;
|
---|
1436 | }
|
---|
1437 | }
|
---|
1438 |
|
---|
1439 |
|
---|
1440 | //draw with this model
|
---|
1441 | g1_quad_object_class *model = draw_params.model;
|
---|
1442 |
|
---|
1443 | //3d vectors
|
---|
1444 | i4_transform_class out;
|
---|
1445 | i4_transform_class *old = context->transform;
|
---|
1446 | context->transform = &out;
|
---|
1447 |
|
---|
1448 | out.multiply(*old, *world_transform);
|
---|
1449 |
|
---|
1450 | if (this!=local_stank ||
|
---|
1451 | !g1_current_controller.get() ||
|
---|
1452 | g1_current_controller->view.get_view_mode()!=G1_ACTION_MODE)
|
---|
1453 | {
|
---|
1454 | g1_render.render_object(model,
|
---|
1455 | &out,
|
---|
1456 | world_transform,
|
---|
1457 | 1,
|
---|
1458 | player_num,
|
---|
1459 | draw_params.frame,
|
---|
1460 | bbox,
|
---|
1461 | 0);
|
---|
1462 | }
|
---|
1463 |
|
---|
1464 | turret->offset.x = i4_interpolate(lturret_kick, turret_kick, g1_render.frame_ratio);
|
---|
1465 |
|
---|
1466 |
|
---|
1467 | // draw barrel with alpha if in action mode and on the local supertank
|
---|
1468 | if (this==local_stank &&
|
---|
1469 | g1_current_controller.get() &&
|
---|
1470 | g1_current_controller->view.get_view_mode()==G1_ACTION_MODE)
|
---|
1471 | {
|
---|
1472 |
|
---|
1473 | // g1_render.r_api->set_alpha_mode(R1_ALPHA_CONSTANT);
|
---|
1474 | // g1_render.r_api->set_write_mode(R1_COMPARE_W | R1_WRITE_COLOR);
|
---|
1475 | // g1_render.r_api->set_shading_mode(R1_COLORED_SHADING);
|
---|
1476 | // g1_render.r_api->set_constant_color((w32)(0.80 * 255) << 24);
|
---|
1477 |
|
---|
1478 | i4_3d_vector r = turret->rotation;
|
---|
1479 | i4_3d_vector old_r = turret->lrotation;
|
---|
1480 |
|
---|
1481 | turret->rotation.z = turret->rotation.z - theta;
|
---|
1482 | turret->lrotation.z = turret->lrotation.z - ltheta;
|
---|
1483 |
|
---|
1484 | i4_transform_class turret_local;
|
---|
1485 | turret->calc_transform(g1_render.frame_ratio, &turret_local);
|
---|
1486 |
|
---|
1487 | turret->draw(context,
|
---|
1488 | world_transform,
|
---|
1489 | bbox,
|
---|
1490 | player_num,
|
---|
1491 | &turret_local);
|
---|
1492 |
|
---|
1493 | turret->rotation = r;
|
---|
1494 | turret->lrotation = old_r;
|
---|
1495 |
|
---|
1496 | // g1_render.r_api->set_alpha_mode(R1_ALPHA_DISABLED);
|
---|
1497 | // g1_render.r_api->set_write_mode(R1_COMPARE_W | R1_WRITE_W | R1_WRITE_COLOR);
|
---|
1498 | }
|
---|
1499 | else
|
---|
1500 | {
|
---|
1501 | i4_3d_vector r = turret->rotation;
|
---|
1502 | i4_3d_vector old_r = turret->lrotation;
|
---|
1503 |
|
---|
1504 | turret->rotation.x = 0;
|
---|
1505 | turret->lrotation.x = 0;
|
---|
1506 |
|
---|
1507 | turret->rotation.y = 0;
|
---|
1508 | turret->lrotation.y = 0;
|
---|
1509 |
|
---|
1510 | turret->rotation.z = turret->rotation.z - theta;
|
---|
1511 | turret->lrotation.z = turret->lrotation.z - ltheta;
|
---|
1512 |
|
---|
1513 | turret->draw(context,
|
---|
1514 | world_transform,
|
---|
1515 | bbox,
|
---|
1516 | player_num);
|
---|
1517 |
|
---|
1518 | turret->rotation = r;
|
---|
1519 | turret->lrotation = old_r;
|
---|
1520 | }
|
---|
1521 |
|
---|
1522 | //get back the old context transform
|
---|
1523 | context->transform = old;
|
---|
1524 |
|
---|
1525 | g1_render.set_render_damage_level(-1);
|
---|
1526 |
|
---|
1527 | if (path)
|
---|
1528 | {
|
---|
1529 | i4_3d_point_class a(x,y,h+0.1),b(dest_x,dest_y,0),c;
|
---|
1530 |
|
---|
1531 | b.z = g1_get_map()->terrain_height(b.x,b.y)+0.1;
|
---|
1532 | c = b;
|
---|
1533 | g1_path_manager.get_nth_position(path,1,c.x,c.y);
|
---|
1534 | c.z = g1_get_map()->terrain_height(c.x,c.y)+0.1;
|
---|
1535 | g1_render.render_3d_line(a,b,0x00ff00,0x00ff00,context->transform);
|
---|
1536 | g1_render.render_3d_line(b,c,0x00ff00,0x00ff00,context->transform);
|
---|
1537 | }
|
---|
1538 |
|
---|
1539 | }
|
---|
1540 |
|
---|
1541 |
|
---|
1542 | void g1_player_piece_class::get_bullet_exit(i4_3d_vector &pos,
|
---|
1543 | i4_3d_vector &dir)
|
---|
1544 | {
|
---|
1545 | #if 1
|
---|
1546 | i4_3d_vector r = turret->rotation;
|
---|
1547 | i4_3d_vector lr = turret->lrotation;
|
---|
1548 |
|
---|
1549 | turret->rotation.z = turret->rotation.z - theta;
|
---|
1550 | turret->lrotation.z = turret->lrotation.z - ltheta;
|
---|
1551 |
|
---|
1552 | i4_transform_class t, main, l2w;
|
---|
1553 | turret->calc_transform(1.0, &t);
|
---|
1554 | calc_world_transform(1.0, &main);
|
---|
1555 | l2w.multiply(main, t);
|
---|
1556 |
|
---|
1557 | l2w.transform(muzzle_exit, pos);
|
---|
1558 | dir=l2w.x;
|
---|
1559 |
|
---|
1560 | turret->rotation = r;
|
---|
1561 | turret->lrotation = lr;
|
---|
1562 | #else
|
---|
1563 | i4_transform_class spare_transform;
|
---|
1564 |
|
---|
1565 | i4_transform_class temp_transform;
|
---|
1566 |
|
---|
1567 | spare_transform.identity();
|
---|
1568 |
|
---|
1569 | temp_transform.rotate_x(groundroll);
|
---|
1570 | spare_transform.multiply(temp_transform);
|
---|
1571 |
|
---|
1572 | temp_transform.rotate_y(groundpitch);
|
---|
1573 | spare_transform.multiply(temp_transform);
|
---|
1574 |
|
---|
1575 | temp_transform.rotate_z(turret->rotation.z);
|
---|
1576 | spare_transform.multiply(temp_transform);
|
---|
1577 |
|
---|
1578 | temp_transform.rotate_y(turret->rotation.y);
|
---|
1579 | spare_transform.multiply(temp_transform);
|
---|
1580 |
|
---|
1581 | i4_3d_vector bullet_pos;
|
---|
1582 | i4_3d_vector bullet_dir;
|
---|
1583 | i4_3d_vector tmp;
|
---|
1584 |
|
---|
1585 | bullet_pos.x = g1_resources.player_turret_radius;
|
---|
1586 | bullet_pos.y = 0.023;
|
---|
1587 | bullet_pos.z = 0.17;
|
---|
1588 |
|
---|
1589 | bullet_dir.x = g1_resources.bullet_speed;
|
---|
1590 | bullet_dir.y = 0;
|
---|
1591 | bullet_dir.z = 0;
|
---|
1592 |
|
---|
1593 | spare_transform.transform(bullet_pos, pos);
|
---|
1594 |
|
---|
1595 | pos.x += x;
|
---|
1596 | pos.y += y;
|
---|
1597 | pos.z += h;
|
---|
1598 |
|
---|
1599 | spare_transform.transform(bullet_dir, dir);
|
---|
1600 | #endif
|
---|
1601 | }
|
---|
1602 |
|
---|
1603 | g1_player_piece_class::~g1_player_piece_class()
|
---|
1604 | {
|
---|
1605 | if (player_num==g1_player_man.local_player)
|
---|
1606 | g1_hurt_tint=0;
|
---|
1607 | }
|
---|
1608 |
|
---|
1609 |
|
---|
1610 | static int first_hurt=1;
|
---|
1611 |
|
---|
1612 | void g1_player_piece_class::damage(g1_object_class *obj, int hp, i4_3d_vector _damage_dir)
|
---|
1613 | {
|
---|
1614 | if (player_num == g1_player_man.local_player)
|
---|
1615 | {
|
---|
1616 | if (hp>10)
|
---|
1617 | {
|
---|
1618 | i4_angle dir = i4_atan2(_damage_dir.y, _damage_dir.x);
|
---|
1619 |
|
---|
1620 | dir -= theta;
|
---|
1621 | i4_normalize_angle(dir);
|
---|
1622 |
|
---|
1623 | if (dir>i4_pi())
|
---|
1624 | roll = 0.08;
|
---|
1625 | else
|
---|
1626 | roll = -0.08;
|
---|
1627 | }
|
---|
1628 |
|
---|
1629 | hurt += i4_f_to_i(hp)/100.0;
|
---|
1630 | hurt = (hurt>0.99999)?0.99999 : hurt;
|
---|
1631 |
|
---|
1632 | if (first_hurt)
|
---|
1633 | {
|
---|
1634 | first_hurt=0;
|
---|
1635 | return_to_repair.play();
|
---|
1636 | }
|
---|
1637 |
|
---|
1638 | if (health!=0 && health-hp<=0)
|
---|
1639 | {
|
---|
1640 | if (g1_current_controller.get())
|
---|
1641 | {
|
---|
1642 | g1_current_controller->view.suggest_camera_mode(G1_CIRCLE_WAIT,
|
---|
1643 | global_id);
|
---|
1644 | g1_current_controller->scroll_message("Death cometh. Press any Key..");
|
---|
1645 | }
|
---|
1646 | }
|
---|
1647 |
|
---|
1648 | }
|
---|
1649 |
|
---|
1650 | if (health!=0 && health-hp<=0)
|
---|
1651 | {
|
---|
1652 | g1_player_man.get(player_num)->continue_wait=1;
|
---|
1653 | theta = base_angle;
|
---|
1654 | g1_create_carcass(this, stank_carcass.get());
|
---|
1655 | }
|
---|
1656 |
|
---|
1657 | if ((stank_flags & ST_GODMODE)==0)
|
---|
1658 | g1_map_piece_class::damage(obj, hp, _damage_dir);
|
---|
1659 |
|
---|
1660 | }
|
---|
1661 |
|
---|
1662 | void g1_player_piece_class::notify_damage(g1_object_class *obj, sw32 hp)
|
---|
1663 | {
|
---|
1664 | // did we kill this guy?
|
---|
1665 | if (obj->health-hp<=0 && obj->get_flag(DANGEROUS))
|
---|
1666 | g1_player_man.get(player_num)->add_points(obj->get_type()->defaults->cost);
|
---|
1667 | }
|
---|
1668 |
|
---|
1669 | void g1_player_piece_class::calc_action_cam(g1_camera_info_struct &cam,
|
---|
1670 | float fr)
|
---|
1671 | {
|
---|
1672 | i4_transform_class cam_transform;
|
---|
1673 |
|
---|
1674 | i4_3d_vector interp_pos,tmp;
|
---|
1675 | interp_pos.interpolate(i4_3d_vector(lx,ly,lh), i4_3d_vector(x,y,h), fr);
|
---|
1676 |
|
---|
1677 | cam.ground_rotate = i4_interpolate_angle(turret->lrotation.z, turret->rotation.z, fr);
|
---|
1678 | cam.horizon_rotate = i4_interpolate_angle(turret->lrotation.y, turret->rotation.y, fr);
|
---|
1679 | cam.roll = i4_interpolate_angle(lroll, roll, fr);
|
---|
1680 | cam.ground_x_rotate = i4_interpolate_angle(lgroundroll, groundroll, fr);
|
---|
1681 | cam.ground_y_rotate = i4_interpolate_angle(lgroundpitch, groundpitch, fr);
|
---|
1682 |
|
---|
1683 | cam_transform.translate(interp_pos.x, interp_pos.y, interp_pos.z);
|
---|
1684 |
|
---|
1685 | cam_transform.mult_rotate_x(cam.ground_x_rotate);
|
---|
1686 | cam_transform.mult_rotate_y(cam.ground_y_rotate);
|
---|
1687 | cam_transform.mult_rotate_z(cam.ground_rotate);
|
---|
1688 | cam_transform.mult_rotate_y(cam.horizon_rotate);
|
---|
1689 |
|
---|
1690 | //hardcoded position of the camera, relative to (0,0,0) of the turret model
|
---|
1691 | cam_transform.transform(i4_3d_vector(0.15, 0.023, 0.12), tmp);
|
---|
1692 |
|
---|
1693 | cam.gx = tmp.x;
|
---|
1694 | cam.gy = tmp.y;
|
---|
1695 | cam.gz = tmp.z;
|
---|
1696 | }
|
---|