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