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