]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/turrets/unit/walker.qc
Fix walker movement
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / turrets / unit / walker.qc
1 #ifdef REGISTER_TURRET
2 REGISTER_TURRET(
3 /* TUR_##id   */ WALKER,
4 /* function   */ t_walker,
5 /* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE,
6 /* mins,maxs  */ '-70 -70 0', '70 70 95',
7 /* model          */ "walker_body.md3",
8 /* head_model */ "walker_head_minigun.md3",
9 /* netname        */ "walker",
10 /* fullname   */ _("Walker Turret")
11 );
12
13 #define WALKER_SETTINGS(turret) \
14         TUR_ADD_CVAR(turret, melee_damage) \
15         TUR_ADD_CVAR(turret, melee_force) \
16         TUR_ADD_CVAR(turret, melee_range) \
17         TUR_ADD_CVAR(turret, rocket_damage) \
18         TUR_ADD_CVAR(turret, rocket_radius) \
19         TUR_ADD_CVAR(turret, rocket_force) \
20         TUR_ADD_CVAR(turret, rocket_speed) \
21         TUR_ADD_CVAR(turret, rocket_range) \
22         TUR_ADD_CVAR(turret, rocket_range_min) \
23         TUR_ADD_CVAR(turret, rocket_refire) \
24         TUR_ADD_CVAR(turret, rocket_turnrate) \
25         TUR_ADD_CVAR(turret, speed_stop) \
26         TUR_ADD_CVAR(turret, speed_walk) \
27         TUR_ADD_CVAR(turret, speed_run) \
28         TUR_ADD_CVAR(turret, speed_jump) \
29         TUR_ADD_CVAR(turret, speed_swim) \
30         TUR_ADD_CVAR(turret, speed_roam) \
31         TUR_ADD_CVAR(turret, turn) \
32         TUR_ADD_CVAR(turret, turn_walk) \
33         TUR_ADD_CVAR(turret, turn_strafe) \
34         TUR_ADD_CVAR(turret, turn_swim) \
35         TUR_ADD_CVAR(turret, turn_run) 
36
37
38 #ifdef SVQC
39 WALKER_SETTINGS(walker)
40 #endif // SVQC
41 #else
42 #ifdef SVQC
43
44 #define ANIM_NO         0
45 #define ANIM_TURN       1
46 #define ANIM_WALK       2
47 #define ANIM_RUN        3
48 #define ANIM_STRAFE_L   4
49 #define ANIM_STRAFE_R   5
50 #define ANIM_JUMP       6
51 #define ANIM_LAND       7
52 #define ANIM_PAIN       8
53 #define ANIM_MELEE      9
54 #define ANIM_SWIM       10
55 #define ANIM_ROAM       11
56
57 .float animflag;
58 .float idletime;
59
60 #define WALKER_PATH(s,e) pathlib_astar(s,e)
61
62 float walker_firecheck()
63 {
64         if (self.animflag == ANIM_MELEE)
65                 return 0;
66
67         return turret_firecheck();
68 }
69
70 void walker_melee_do_dmg()
71 {
72         vector where;
73         entity e;
74
75         makevectors(self.angles);
76         where = self.origin + v_forward * 128;
77
78         e = findradius(where,32);
79         while (e)
80         {
81                 if (turret_validate_target(self, e, self.target_validate_flags))
82                         if (e != self && e.owner != self)
83                                 Damage(e, self, self, TUR_CVAR(walker, melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * TUR_CVAR(walker, melee_force));
84
85                 e = e.chain;
86         }
87 }
88
89 void walker_setnoanim()
90 {
91         turrets_setframe(ANIM_NO, FALSE);
92         self.animflag = self.frame;
93 }
94 void walker_rocket_explode()
95 {
96         RadiusDamage (self, self.owner, TUR_CVAR(walker, rocket_damage), 0, TUR_CVAR(walker, rocket_radius), self, TUR_CVAR(walker, rocket_force), DEATH_TURRET_WALK_ROCKET, world);
97         remove (self);
98 }
99
100 void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
101 {
102         self.health = self.health - damage;
103         self.velocity = self.velocity + vforce;
104
105         if (self.health <= 0)
106                 W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
107 }
108
109 #define WALKER_ROCKET_MOVE movelib_move_simple(newdir, TUR_CVAR(walker, rocket_speed), TUR_CVAR(walker, rocket_turnrate)); UpdateCSQCProjectile(self)
110 void walker_rocket_loop();
111 void walker_rocket_think()
112 {
113         vector newdir;
114         float edist;
115         float itime;
116         float m_speed;
117
118         self.nextthink = time;
119
120         edist = vlen(self.enemy.origin - self.origin);
121
122         // Simulate crude guidance
123         if (self.cnt < time)
124         {
125                 if (edist < 1000)
126                         self.tur_shotorg = randomvec() * min(edist, 64);
127                 else
128                         self.tur_shotorg = randomvec() * min(edist, 256);
129
130                 self.cnt = time + 0.5;
131         }
132
133         if (edist < 128)
134                 self.tur_shotorg = '0 0 0';
135
136         if (self.max_health < time)
137         {
138                 self.think        = walker_rocket_explode;
139                 self.nextthink  = time;
140                 return;
141         }
142
143         if (self.shot_dmg != 1337 && random() < 0.01)
144         {
145                 walker_rocket_loop();
146                 return;
147         }
148
149         m_speed = vlen(self.velocity);
150
151         // Enemy dead? just keep on the current heading then.
152         if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
153                 self.enemy = world;
154
155         if (self.enemy)
156         {
157                 itime = max(edist / m_speed, 1);
158                 newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
159         }
160         else
161                 newdir  = normalize(self.velocity);
162
163         WALKER_ROCKET_MOVE;
164 }
165
166 void walker_rocket_loop3()
167 {
168         vector newdir;
169         self.nextthink = time;
170
171         if (self.max_health < time)
172         {
173                 self.think = walker_rocket_explode;
174                 return;
175         }
176
177         if (vlen(self.origin - self.tur_shotorg) < 100 )
178         {
179                 self.think = walker_rocket_think;
180                 return;
181         }
182
183         newdir = steerlib_pull(self.tur_shotorg);
184         WALKER_ROCKET_MOVE;
185
186         self.angles = vectoangles(self.velocity);
187 }
188
189 void walker_rocket_loop2()
190 {
191         vector newdir;
192
193         self.nextthink = time;
194
195         if (self.max_health < time)
196         {
197                 self.think = walker_rocket_explode;
198                 return;
199         }
200
201         if (vlen(self.origin - self.tur_shotorg) < 100 )
202         {
203                 self.tur_shotorg = self.origin - '0 0 200';
204                 self.think = walker_rocket_loop3;
205                 return;
206         }
207
208         newdir = steerlib_pull(self.tur_shotorg);
209         WALKER_ROCKET_MOVE;
210 }
211
212 void walker_rocket_loop()
213 {
214         self.nextthink = time;
215         self.tur_shotorg = self.origin + '0 0 300';
216         self.think = walker_rocket_loop2;
217         self.shot_dmg = 1337;
218 }
219
220 void walker_fire_rocket(vector org)
221 {
222         entity rocket;
223
224         fixedmakevectors(self.angles);
225
226         te_explosion (org);
227
228         rocket = spawn ();
229         setorigin(rocket, org);
230
231         sound (self, CH_WEAPON_A, "weapons/hagar_fire.wav", VOL_BASE, ATTEN_NORM);
232         setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
233
234         rocket.classname                  = "walker_rocket";
235         rocket.owner                      = self;
236         rocket.bot_dodge                  = TRUE;
237         rocket.bot_dodgerating  = 50;
238         rocket.takedamage                = DAMAGE_YES;
239         rocket.damageforcescale   = 2;
240         rocket.health                    = 25;
241         rocket.tur_shotorg              = randomvec() * 512;
242         rocket.cnt                              = time + 1;
243         rocket.enemy                      = self.enemy;
244
245         if (random() < 0.01)
246                 rocket.think              = walker_rocket_loop;
247         else
248                 rocket.think              = walker_rocket_think;
249
250         rocket.event_damage        = walker_rocket_damage;
251
252         rocket.nextthink                  = time;
253         rocket.movetype            = MOVETYPE_FLY;
254         rocket.velocity            = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * TUR_CVAR(walker, rocket_speed);
255         rocket.angles                    = vectoangles(rocket.velocity);
256         rocket.touch                      = walker_rocket_explode;
257         rocket.flags                      = FL_PROJECTILE;
258         rocket.solid                      = SOLID_BBOX;
259         rocket.max_health                = time + 9;
260         rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
261
262         CSQCProjectile(rocket, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
263 }
264
265 .vector enemy_last_loc;
266 .float enemy_last_time;
267 void walker_move_to(vector _target, float _dist)
268 {
269         switch (self.waterlevel)
270         {
271                 case WATERLEVEL_NONE:
272                         if (_dist > 500)
273                                 self.animflag = ANIM_RUN;
274                         else
275                                 self.animflag = ANIM_WALK;
276                 case WATERLEVEL_WETFEET:
277                 case WATERLEVEL_SWIMMING:
278                         if (self.animflag != ANIM_SWIM)
279                                 self.animflag = ANIM_WALK;
280                         else
281                                 self.animflag = ANIM_SWIM;
282                         break;
283                 case WATERLEVEL_SUBMERGED:
284                         self.animflag = ANIM_SWIM;
285         }
286
287         self.moveto = _target;
288         self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
289
290         if(self.enemy)
291         {
292                 self.enemy_last_loc = _target;
293                 self.enemy_last_time = time;
294         }
295 }
296
297 //#define WALKER_FANCYPATHING
298
299 void walker_move_path()
300 {
301 #ifdef WALKER_FANCYPATHING
302         // Are we close enougth to a path node to switch to the next?
303         if (vlen(self.origin  - self.pathcurrent.origin) < 64)
304                 if (self.pathcurrent.path_next == world)
305                 {
306                         // Path endpoint reached
307                         pathlib_deletepath(self.pathcurrent.owner);
308                         self.pathcurrent = world;
309
310                         if (self.pathgoal)
311                         {
312                                 if (self.pathgoal.use)
313                                         self.pathgoal.use();
314
315                                 if (self.pathgoal.enemy)
316                                 {
317                                         self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
318                                         self.pathgoal = self.pathgoal.enemy;
319                                 }
320                         }
321                         else
322                                 self.pathgoal = world;
323                 }
324                 else
325                         self.pathcurrent = self.pathcurrent.path_next;
326
327         self.moveto = self.pathcurrent.origin;
328         self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
329         walker_move_to(self.moveto, 0);
330
331 #else
332         if (vlen(self.origin - self.pathcurrent.origin) < 64)
333                 self.pathcurrent = self.pathcurrent.enemy;
334
335         if(!self.pathcurrent)
336                 return;
337
338         self.moveto = self.pathcurrent.origin;
339         self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
340         walker_move_to(self.moveto, 0);
341 #endif
342 }
343
344 void spawnfunc_turret_walker() { if not(turret_initialize(TUR_WALKER)) remove(self); }
345
346 float t_walker(float req)
347 {
348         switch(req)
349         {
350                 case TR_ATTACK:
351                 {
352                         sound (self, CH_WEAPON_A, "weapons/uzi_fire.wav", VOL_BASE, ATTEN_NORM);
353                         fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, self.shot_speed, 5, self.shot_dmg, self.shot_force, DEATH_TURRET_WALK_GUN, 0, 1, autocvar_g_balance_uzi_bulletconstant);
354                         endFireBallisticBullet();
355                         pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
356
357                         return TRUE;
358                 }
359                 case TR_THINK:
360                 {
361                         fixedmakevectors(self.angles);
362
363                         if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
364                                 walker_move_path();
365                         else if (self.enemy == world)
366                         {
367                                 if(self.pathcurrent)
368                                         walker_move_path();
369                                 else
370                                 {
371                                         if(self.enemy_last_time != 0)
372                                         {
373                                                 if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
374                                                         self.enemy_last_time = 0;
375                                                 else
376                                                         walker_move_to(self.enemy_last_loc, 0);
377                                         }
378                                         else
379                                         {
380                                                 if(self.animflag != ANIM_NO)
381                                                 {
382                                                         traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
383
384                                                         if(trace_fraction != 1.0)
385                                                                 self.tur_head.idletime = -1337;
386                                                         else
387                                                         {
388                                                                 traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
389                                                                 if(trace_fraction == 1.0)
390                                                                         self.tur_head.idletime = -1337;
391                                                         }
392
393                                                         if(self.tur_head.idletime == -1337)
394                                                         {
395                                                                 self.moveto = self.origin + randomvec() * 256;
396                                                                 self.tur_head.idletime = 0;
397                                                         }
398
399                                                         self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
400                                                         self.moveto_z = self.origin_z + 64;
401                                                         walker_move_to(self.moveto, 0);
402                                                 }
403
404                                                 if(self.idletime < time)
405                                                 {
406                                                         if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
407                                                         {
408                                                                 self.idletime = time + 1 + random() * 5;
409                                                                 self.moveto = self.origin;
410                                                                 self.animflag = ANIM_NO;
411                                                         }
412                                                         else
413                                                         {
414                                                                 self.animflag = ANIM_WALK;
415                                                                 self.idletime = time + 4 + random() * 2;
416                                                                 self.moveto = self.origin + randomvec() * 256;
417                                                                 self.tur_head.moveto = self.moveto;
418                                                                 self.tur_head.idletime = 0;
419                                                         }
420                                                 }
421                                         }
422                                 }
423                         }
424                         else
425                         {
426                                 if (self.tur_dist_enemy < TUR_CVAR(walker, melee_range) && self.animflag != ANIM_MELEE)
427                                 {
428                                         vector wish_angle;
429
430                                         wish_angle = angleofs(self, self.enemy);
431                                         if (self.animflag != ANIM_SWIM)
432                                         if (fabs(wish_angle_y) < 15)
433                                         {
434                                                 self.moveto   = self.enemy.origin;
435                                                 self.steerto  = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
436                                                 self.animflag = ANIM_MELEE;
437                                         }
438                                 }
439                                 else if (self.tur_head.attack_finished_single < time)
440                                 {
441                                         if(self.tur_head.shot_volly)
442                                         {
443                                                 self.animflag = ANIM_NO;
444
445                                                 self.tur_head.shot_volly = self.tur_head.shot_volly -1;
446                                                 if(self.tur_head.shot_volly == 0)
447                                                         self.tur_head.attack_finished_single = time + TUR_CVAR(walker, rocket_refire);
448                                                 else
449                                                         self.tur_head.attack_finished_single = time + 0.2;
450
451                                                 if(self.tur_head.shot_volly > 1)
452                                                         walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
453                                                 else
454                                                         walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
455                                         }
456                                         else
457                                         {
458                                                 if (self.tur_dist_enemy > TUR_CVAR(walker, rocket_range_min))
459                                                 if (self.tur_dist_enemy < TUR_CVAR(walker, rocket_range))
460                                                         self.tur_head.shot_volly = 4;
461                                         }
462                                 }
463                                 else
464                                 {
465                                         if (self.animflag != ANIM_MELEE)
466                                                 walker_move_to(self.enemy.origin, self.tur_dist_enemy);
467                                 }
468                         }
469                         
470                         {
471                                 vector real_angle;
472                                 float turny = 0, turnx = 0;
473                                 float vz;
474
475                                 real_angle = vectoangles(self.steerto) - self.angles;
476                                 vz = self.velocity_z;
477
478                                 switch (self.animflag)
479                                 {
480                                         case ANIM_NO:
481                                                 movelib_beak_simple(TUR_CVAR(walker, speed_stop));
482                                                 break;
483
484                                         case ANIM_TURN:
485                                                 turny = TUR_CVAR(walker, turn);
486                                                 movelib_beak_simple(TUR_CVAR(walker, speed_stop));
487                                                 break;
488
489                                         case ANIM_WALK:
490                                                 turny = TUR_CVAR(walker, turn_walk);
491                                                 movelib_move_simple(v_forward, TUR_CVAR(walker, speed_walk), 0.6);
492                                                 break;
493
494                                         case ANIM_RUN:
495                                                 turny = TUR_CVAR(walker, turn_run);
496                                                 movelib_move_simple(v_forward, TUR_CVAR(walker, speed_run), 0.6);
497                                                 break;
498
499                                         case ANIM_STRAFE_L:
500                                                 turny = TUR_CVAR(walker, turn_strafe);
501                                                 movelib_move_simple(v_right * -1, TUR_CVAR(walker, speed_walk), 0.8);
502                                                 break;
503
504                                         case ANIM_STRAFE_R:
505                                                 turny = TUR_CVAR(walker, turn_strafe);
506                                                 movelib_move_simple(v_right, TUR_CVAR(walker, speed_walk), 0.8);
507                                                 break;
508
509                                         case ANIM_JUMP:
510                                                 self.velocity += '0 0 1' * TUR_CVAR(walker, speed_jump);
511                                                 break;
512
513                                         case ANIM_LAND:
514                                                 break;
515
516                                         case ANIM_PAIN:
517                                                 if(self.frame != ANIM_PAIN)
518                                                         defer(0.25, walker_setnoanim);
519
520                                                 break;
521
522                                         case ANIM_MELEE:
523                                                 if(self.frame != ANIM_MELEE)
524                                                 {
525                                                         defer(0.41, walker_setnoanim);
526                                                         defer(0.21, walker_melee_do_dmg);
527                                                 }
528
529                                                 movelib_beak_simple(TUR_CVAR(walker, speed_stop));
530                                                 break;
531
532                                         case ANIM_SWIM:
533                                                 turny = TUR_CVAR(walker, turn_swim);
534                                                 turnx = TUR_CVAR(walker, turn_swim);
535
536                                                 self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
537                                                 movelib_move_simple(v_forward, TUR_CVAR(walker, speed_swim), 0.3);
538                                                 vz = self.velocity_z + sin(time * 4) * 8;
539                                                 break;
540
541                                         case ANIM_ROAM:
542                                                 turny = TUR_CVAR(walker, turn_walk);
543                                                 movelib_move_simple(v_forward ,TUR_CVAR(walker, speed_roam), 0.5);
544                                                 break;
545                                 }
546
547                                 if(turny)
548                                 {
549                                         turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
550                                         self.angles_y += turny;
551                                 }
552
553                                 if(turnx)
554                                 {
555                                         turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
556                                         self.angles_x += turnx;
557                                 }
558
559                                 self.velocity_z = vz;
560                         }
561
562
563                         if(self.origin != self.oldorigin)
564                                 self.SendFlags |= TNSF_MOVE;
565
566                         self.oldorigin = self.origin;
567                         turrets_setframe(self.animflag, FALSE);
568
569                         return TRUE;
570                 }
571                 case TR_DEATH:
572                 {
573 #ifdef WALKER_FANCYPATHING
574                         if (self.pathcurrent)
575                                 pathlib_deletepath(self.pathcurrent.owner);
576 #endif
577                         self.pathcurrent = world;
578                 
579                         return TRUE;
580                 }
581                 case TR_SETUP:
582                 {
583                         self.ticrate = 0.05;
584                         
585                         entity e;
586
587                         // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
588                         if(self.movetype == MOVETYPE_WALK)
589                         {
590                                 if(self.pos1)
591                                         setorigin(self, self.pos1);
592                                 if(self.pos2)
593                                         self.angles = self.pos2;
594                         }
595                         
596                         self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
597                         self.aim_flags = TFL_AIM_LEAD;
598
599                         if (autocvar_g_antilag_bullets)
600                                 self.turret_flags |= TUR_FLAG_HITSCAN;
601                         else
602                                 self.aim_flags |= TFL_AIM_SHOTTIMECOMPENSATE;
603                                 
604                         self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
605                         self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
606                         self.iscreature = TRUE;
607                         self.teleportable = TELEPORT_NORMAL;
608                         self.damagedbycontents = TRUE;
609                         self.solid = SOLID_SLIDEBOX;
610                         self.takedamage = DAMAGE_AIM;
611                         if(self.movetype != MOVETYPE_WALK)
612                         {
613                                 setorigin(self, self.origin);
614                                 tracebox(self.origin + '0 0 128', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_NORMAL, self);
615                                 setorigin(self, trace_endpos + '0 0 4');
616                                 self.pos1 = self.origin;
617                                 self.pos2 = self.angles;
618                         }
619                         self.movetype = MOVETYPE_WALK;
620                         self.idle_aim = '0 0 0';
621                         self.turret_firecheckfunc = walker_firecheck;
622                         
623                         if (self.target != "")
624                         {
625                                 e = find(world, targetname, self.target);
626                                 if (!e)
627                                 {
628                                         dprint("Initital waypoint for walker does NOT exsist, fix your map!\n");
629                                         self.target = "";
630                                 }
631
632                                 if (e.classname != "turret_checkpoint")
633                                         dprint("Warning: not a turrret path\n");
634                                 else
635                                 {
636 #ifdef WALKER_FANCYPATHING
637                                         self.pathcurrent = WALKER_PATH(self.origin, e.origin);
638                                         self.pathgoal = e;
639 #else
640                                         self.pathcurrent = e;
641 #endif
642                                 }
643                         }
644
645                         return TRUE;
646                 }
647                 case TR_PRECACHE:
648                 {
649                         precache_model ("models/turrets/walker_body.md3");
650                         precache_model ("models/turrets/walker_head_minigun.md3");
651                         precache_model ("models/turrets/rocket.md3");
652                         precache_sound ("weapons/rocket_impact.wav");
653                         return TRUE;
654                 }
655                 case TR_CONFIG:
656                 {
657                         TUR_CONFIG_SETTINGS(WALKER_SETTINGS(walker))
658                         return TRUE;
659                 }
660         }
661
662         return TRUE;
663 }
664
665 #endif // SVQC
666 #ifdef CSQC
667
668 void walker_draw()
669 {
670         float dt;
671
672         dt = time - self.move_time;
673         self.move_time = time;
674         if(dt <= 0)
675                 return;
676
677         fixedmakevectors(self.angles);
678         movelib_groundalign4point(300, 100, 0.25, 45);
679         setorigin(self, self.origin + self.velocity * dt);
680         self.tur_head.angles += dt * self.tur_head.move_avelocity;
681         self.angles_y = self.move_angles_y;
682
683         if (self.health < 127)
684         if(random() < 0.15)
685                 te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
686 }
687
688 float t_walker(float req)
689 {
690         switch(req)
691         {
692                 case TR_SETUP:
693                 {
694                         self.gravity            = 1;
695                         self.movetype           = MOVETYPE_BOUNCE;
696                         self.move_movetype      = MOVETYPE_BOUNCE;
697                         self.move_origin        = self.origin;
698                         self.move_time          = time;
699                         self.draw                       = walker_draw;
700                         
701                         return TRUE;
702                 }
703                 case TR_PRECACHE:
704                 {
705                         precache_model ("models/turrets/walker_body.md3");
706                         precache_model ("models/turrets/walker_head_minigun.md3");
707                         return TRUE;
708                 }
709         }
710
711         return TRUE;
712 }
713
714 #endif // CSQC
715 #endif // REGISTER_TURRET