]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/tturrets/units/unit_walker.qc
Fix accuracy stats (#400)
[divverent/nexuiz.git] / data / qcsrc / server / tturrets / units / unit_walker.qc
1 #define ANIM_NO         0
2 #define ANIM_REVERSE    1
3 #define ANIM_WALK       2
4 #define ANIM_RUN        3
5 #define ANIM_STRAFE_L   4
6 #define ANIM_STRAFE_R   5
7 #define ANIM_TURN       6
8 #define ANIM_JUMP       7
9 #define ANIM_LAND       8
10 #define ANIM_PAIN       9
11 #define ANIM_MEELE      10
12 #define ANIM_SWIM       11
13 #define ANIM_ROAM       12
14
15 #define WVM_IDLE_UP 25
16 #define WVM_IDLE    50
17
18 #define WVM_PATH  1000
19 #define WVM_ENEMY 2000
20 #define WVM_STOP  3000
21 #define WVM_DODGE 4000
22 #define  WVM_PANIC 10000
23 #define walker_verbs_move verbs_move
24
25 #define WVA_MINIGUN 100
26 #define WVA_ROCKET  500
27 #define WVA_MEELE   1000
28 #define walker_verbs_attack verbs_attack
29
30 #define WVI_IDLE 1
31 #define WVI_ROAM 10
32 #define walker_verbs_idle verbs_idle
33
34 .float animflag;
35 .entity wkr_spawn;
36
37 #define WALKER_MIN '-70 -70 5'
38 #define WALKER_MAX '70 70 70'
39
40 #define WALKER_PATH(s,e) pathlib_astar(s,e)
41
42 float walker_firecheck()
43 {
44     if (self.animflag == ANIM_MEELE)
45         return 0;
46
47     return turret_stdproc_firecheck();
48 }
49
50 void walker_meele_do_dmg()
51 {
52     vector where;
53     entity e;
54     makevectors(self.angles);
55     where = self.origin + v_forward * 128;
56
57     //w_deathtypestring = "tried to hug the cute spider thingy.";
58     e = findradius(where,64);
59     while (e)
60     {
61         if (turret_validate_target(self,e,self.target_validate_flags))
62             if (e != self && e.owner != self)
63                 Damage(e,self,self,cvar("g_turrets_unit_walker_std_meele_dmg"),DEATH_TURRET,'0 0 0', v_forward * cvar("g_turrets_unit_walker_std_meele_force") );
64
65         e = e.chain;
66     }
67 }
68
69 void walker_animate()
70 {
71     vector real_angle;
72     float  vz;
73
74     real_angle = vectoangles(self.steerto) - self.angles;
75     vz         = self.velocity_z;
76
77     if (self.tur_head.frame != 0)
78         self.tur_head.frame = self.tur_head.frame +1;
79
80     if (self.tur_head.frame > 12)
81         self.tur_head.frame = 0;
82
83     switch (self.animflag)
84     {
85
86     case ANIM_NO:
87         if (self.frame != 0)
88             self.frame = 0;
89
90         movelib_beak_simple(cvar("g_turrets_unit_walker_speed_stop"));
91
92         break;
93
94     case ANIM_REVERSE:
95         if ((self.frame < 5) || (self.frame > 25))
96             self.frame = 25;
97
98         self.frame = self.frame -1;
99         movelib_move_simple(v_forward * -1 ,cvar("g_turrets_unit_walker_speed_walk"),0.6);
100
101         if (self.frame < 5)
102             self.frame = 25;
103
104         break;
105
106     case ANIM_TURN:
107
108         if ((self.frame < 30) || (self.frame > 55))
109             self.frame = 30;
110
111         self.frame = self.frame + 1;
112
113         self.angles_y += bound(-15,shortangle_f(real_angle_y,self.angles_y),15);
114
115         movelib_beak_simple(cvar("g_turrets_unit_walker_speed_stop"));
116
117         if (self.frame > 55)
118             self.frame = 35;
119
120         break;
121
122     case ANIM_WALK:
123         if ((self.frame < 5) || (self.frame > 25))
124             self.frame = 5;
125
126         self.frame = self.frame +1;
127         self.angles_y += bound(-10,shortangle_f(real_angle_y,self.angles_y),10);
128         movelib_move_simple(v_forward ,cvar("g_turrets_unit_walker_speed_walk"),0.6);
129
130         if (self.frame > 25)
131             self.frame = 5;
132
133         break;
134
135     case ANIM_ROAM:
136         if ((self.frame < 5) || (self.frame > 25))
137             self.frame = 5;
138
139         self.frame = self.frame +1;
140
141         self.angles_y += bound(-5,shortangle_f(real_angle_y,self.angles_y),5);
142
143         movelib_move_simple(v_forward ,cvar("g_turrets_unit_walker_speed_roam"),0.5);
144
145         if (self.frame > 25)
146             self.frame = 5;
147
148         break;
149
150     case ANIM_SWIM:
151         if ((self.frame < 142) || (self.frame > 151))
152             self.frame = 142;
153
154         self.frame = self.frame +1;
155
156         self.angles_y += bound(-10,shortangle_f(real_angle_y,self.angles_y),10);
157         self.angles_x += bound(-10,shortangle_f(real_angle_x,self.angles_x),10);
158
159         movelib_move_simple(v_forward, cvar("g_turrets_unit_walker_speed_swim"),0.3);
160         vz = self.velocity_z + sin(time * 4) * 8;
161
162         if (self.frame > 151)
163             self.frame = 146;
164
165         break;
166
167     case ANIM_RUN:
168
169         if ((self.frame < 5) || (self.frame > 25))
170             self.frame = 5;
171
172         self.angles_y += bound(-5,shortangle_f(real_angle_y,self.angles_y),5);
173         movelib_move_simple(v_forward, cvar("g_turrets_unit_walker_speed_run"),0.6);
174
175         if (self.frame > 25)
176             self.frame = 5;
177
178         break;
179
180     case ANIM_STRAFE_L:
181         if ((self.frame < 30) || (self.frame > 55))
182             self.frame = 30;
183
184         self.frame = self.frame + 1;
185         self.angles_y += bound(-2.5,shortangle_f(real_angle_y,self.angles_y),2.5);
186         movelib_move_simple(v_right * -1, cvar("g_turrets_unit_walker_speed_walk"),0.8);
187
188         if (self.frame > 55)
189             self.frame = 35;
190         break;
191
192     case ANIM_STRAFE_R:
193         if ((self.frame < 60) || (self.frame > 65))
194             self.frame = 60;
195
196         self.frame = self.frame + 1;
197         self.angles_y += bound(-2.5,shortangle_f(real_angle_y,self.angles_y),2.5);
198         movelib_move_simple(v_right, cvar("g_turrets_unit_walker_speed_walk"),0.8);
199
200         if (self.frame > 85)
201             self.frame = 65;
202
203         break;
204
205     case ANIM_JUMP:
206         if ((self.frame < 95) || (self.frame > 100))
207             self.frame = 95;
208
209         self.velocity += '0 0 1' * cvar("g_turrets_unit_walker_speed_jump");
210
211         if (self.frame > 100)
212             self.frame = self.frame + 1;
213
214         break;
215
216     case ANIM_LAND:
217         if ((self.frame < 100) || (self.frame > 107))
218             self.frame = 100;
219
220         self.frame = self.frame + 1;
221
222         if (self.frame > 107)
223             self.animflag = ANIM_NO;
224
225         break;
226
227     case ANIM_PAIN:
228         if ((self.frame < 60) || (self.frame > 95))
229             self.frame = 90;
230
231         self.frame = self.frame + 1;
232
233         if (self.frame > 95)
234             self.animflag = ANIM_NO;
235
236         break;
237
238     case ANIM_MEELE:
239         if ((self.frame < 123) || (self.frame > 140))
240             self.frame = 123;
241
242         movelib_beak_simple(cvar("g_turrets_unit_walker_speed_stop"));
243
244         self.frame = self.frame + 2;
245
246         if (self.frame == 133)
247             walker_meele_do_dmg();
248
249         if (self.frame > 140)
250         {
251             self.animflag = ANIM_NO;
252             self.frame = 0;
253         }
254     }
255
256     self.velocity_z = vz;
257
258     if (self.flags & FL_ONGROUND)
259         movelib_groundalign4point(300,100,0.25);
260
261 }
262
263
264 void walker_rocket_explode()
265 {
266     vector org2;
267
268     if (self.event_damage != SUB_Null)
269     {
270         self.event_damage = SUB_Null;
271         self.think = walker_rocket_explode;
272         self.nextthink = time;
273         return;
274     }
275
276     sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
277     org2 = findbetterlocation (self.origin, 16);
278
279     pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
280     //w_deathtypestring = "got blasted to oblivion";
281     RadiusDamage (self, self.owner, cvar("g_turrets_unit_walker_std_rocket_dmg"), 0, cvar("g_turrets_unit_walker_std_rocket_radius"), world, cvar("g_turrets_unit_walker_std_rocket_force"), DEATH_TURRET, world, 0);
282
283     remove (self);
284 }
285
286 void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
287 {
288     self.health = self.health - damage;
289     self.velocity = self.velocity + vforce;
290     if (self.health <= 0)
291         walker_rocket_explode();
292 }
293
294 #define WALKER_ROCKET_MOVE movelib_move_simple(newdir,cvar("g_turrets_unit_walker_std_rocket_speed"),cvar("g_turrets_unit_walker_std_rocket_tunrate")); UpdateCSQCProjectile(self)
295 void walker_rocket_loop();
296 void walker_rocket_think()
297 {
298     vector newdir;
299     float edist;
300     float itime;
301     float m_speed;
302
303     self.nextthink = time;
304
305     edist = vlen(self.enemy.origin - self.origin);
306
307     // Simulate crude guidance
308     if (self.cnt < time)
309     {
310         if (edist < 1000)
311             self.tur_shotorg = randomvec() * min(edist,64);
312         else
313             self.tur_shotorg = randomvec() * min(edist,256);
314
315         self.cnt = time + 0.5;
316     }
317
318     if (edist < 256)
319         self.tur_shotorg = '0 0 0';
320
321
322     if (self.tur_health < time)
323     {
324         self.think = walker_rocket_explode;
325         self.nextthink = time;
326         return;
327     }
328
329     if (self.shot_dmg != 1337)
330         if (random() < 0.01)
331         {
332             walker_rocket_loop();
333             return;
334         }
335
336     m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
337
338     // Enemy dead? just keep on the current heading then.
339     if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
340     {
341         // Make sure we dont return to tracking a respawned player
342         self.enemy = world;
343     }
344
345     if (self.enemy)
346     {
347         itime = max(edist / m_speed,1);
348         newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
349     }
350     else
351     {
352         newdir  = normalize(self.velocity);
353     }
354
355     WALKER_ROCKET_MOVE;
356 }
357
358 void walker_rocket_loop3()
359 {
360     vector newdir;
361     self.nextthink = time;
362
363     if (self.tur_health < time)
364     {
365         self.think = walker_rocket_explode;
366         return;
367     }
368
369     if (vlen(self.origin - self.tur_shotorg) < 128 )
370     {
371         self.think = walker_rocket_think;
372         return;
373     }
374
375     newdir = steerlib_pull(self.tur_shotorg);
376     WALKER_ROCKET_MOVE;
377
378     self.angles = vectoangles(self.velocity);
379 }
380
381 void walker_rocket_loop2()
382 {
383     vector newdir;
384
385     self.nextthink = time;
386
387     if (self.tur_health < time)
388     {
389         self.think = walker_rocket_explode;
390         return;
391     }
392
393     if (vlen(self.origin - self.tur_shotorg) < 128 )
394     {
395         self.tur_shotorg = self.origin - '0 0 200';
396         self.think = walker_rocket_loop3;
397         return;
398     }
399
400     newdir = steerlib_pull(self.tur_shotorg);
401     WALKER_ROCKET_MOVE;
402 }
403
404 void walker_rocket_loop()
405 {
406     self.nextthink = time;
407     self.tur_shotorg = self.origin + '0 0 400';
408     self.think = walker_rocket_loop2;
409     self.shot_dmg = 1337;
410 }
411
412 void walker_fire_rocket(vector org)
413 {
414
415     entity rocket;
416
417
418     self.angles_x *= -1;
419     makevectors(self.angles);
420     self.angles_x *= -1;
421
422     te_explosion (org);
423
424     rocket = spawn ();
425     setorigin(rocket, org);
426
427     sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
428     setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
429
430     rocket.classname          = "walker_rocket";
431     rocket.owner              = self;
432
433     rocket.bot_dodge          = TRUE;
434     rocket.bot_dodgerating    = 50;
435
436     rocket.takedamage         = DAMAGE_YES;
437
438     rocket.damageforcescale   = 2;
439     rocket.health             = 25;
440     rocket.tur_shotorg        = randomvec() * 512;
441     rocket.cnt                = time + 1;
442     rocket.enemy              = self.enemy;
443
444     if (random() < 0.01)
445         rocket.think          = walker_rocket_loop;
446     else
447         rocket.think          = walker_rocket_think;
448
449     rocket.event_damage       = walker_rocket_damage;
450
451     rocket.nextthink          = time;// + 0.25;
452     rocket.movetype           = MOVETYPE_FLY;
453     rocket.velocity           = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * cvar("g_turrets_unit_walker_std_rocket_speed");
454     rocket.angles             = vectoangles(rocket.velocity);
455     rocket.touch              = walker_rocket_explode;
456     rocket.flags              = FL_PROJECTILE;
457     rocket.solid              = SOLID_BBOX;
458     rocket.tur_health         = time + 9;
459
460     CSQCProjectile(rocket, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
461 }
462
463 void rv_think()
464 {
465     float f;
466     vector org;
467     entity oldself;
468
469     if (self.owner.deadflag != DEAD_NO)
470     {
471         remove(self);
472         return;
473     }
474
475     self.cnt = self.cnt -1;
476
477     if (self.cnt < 0)
478     {
479         remove(self);
480         return;
481     }
482
483     if (self.cnt > 1)
484         f = gettagindex(self.owner,"tag_rocket01");
485     else
486         f = gettagindex(self.owner,"tag_rocket02");
487
488     org = gettaginfo(self.owner,f);
489
490     self.nextthink = time + 0.2;
491     oldself = self;
492     self = self.owner;
493     walker_fire_rocket(org);
494     self = oldself;
495 }
496
497 float walker_moveverb_path(float eval)
498 {
499     switch (eval)
500     {
501     case VCM_EVAL:
502
503         if (self.animflag == ANIM_MEELE)
504             return VS_CALL_NO;
505
506         if (self.pathcurrent)
507             return verb.verb_static_value;
508
509         return VS_CALL_NO;
510
511     case VCM_DO:
512         // Do we have a path?
513         if not(self.pathcurrent)
514         {
515             return VS_CALL_NO;
516         }
517         else
518         {
519             // Are we close enougth to a path node to switch to the next?
520             if (vlen(self.origin  - self.pathcurrent.origin) < 64)
521                 if (self.pathcurrent.path_next == world)
522                 {
523                     // Path endpoint reached
524                     pathlib_deletepath(self.pathcurrent.owner);
525                     self.pathcurrent = world;
526
527                     if (self.pathgoal)
528                     {
529                         if (self.pathgoal.use)
530                             self.pathgoal.use();
531
532                         if (self.pathgoal.enemy)
533                         {
534                             self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
535                             self.pathgoal = self.pathgoal.enemy;
536                         }
537                     }
538                     else
539                         self.pathgoal = world;
540                 }
541                 else
542                     self.pathcurrent = self.pathcurrent.path_next;
543         }
544
545
546         if (self.pathcurrent)
547         {
548             switch (self.waterlevel)
549             {
550             case 0:
551                 self.animflag = ANIM_WALK;
552             case 1:
553             case 2:
554                 if (self.animflag == ANIM_WALK)
555                     self.animflag = ANIM_WALK;
556                 else
557                     self.animflag = ANIM_SWIM;
558                 break;
559             case 3:
560                 self.animflag = ANIM_SWIM;
561             }
562
563             self.moveto = self.pathcurrent.origin;
564             self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
565
566             return VS_CALL_YES_DOING;
567         }
568         else
569             return VS_CALL_YES_DONE;
570
571     case VCM_REMOVE:
572
573         if (self.pathcurrent)
574             pathlib_deletepath(self.pathcurrent.owner);
575
576         self.pathcurrent = world;
577
578         return VS_CALL_YES_DONE;
579     }
580
581     return VS_CALL_YES_DONE;
582 }
583
584 float walker_moveverb_enemy(float eval)
585 {
586     switch (eval)
587     {
588     case VCM_EVAL:
589
590         if (self.enemy)
591             if (self.spawnflags & TSF_NO_PATHBREAK)
592                 if (self.pathcurrent)
593                     return VS_CALL_NO;
594
595         if (self.animflag == ANIM_MEELE)
596             return VS_CALL_NO;
597
598         if (self.enemy == world)
599             return VS_CALL_NO;
600
601         //if (tracewalk(self.enemy, self.origin, self.mins, self.maxs, self.enemy.origin, MOVE_NORMAL))
602         return verb.verb_static_value;
603
604         //return VS_CALL_NO;
605
606     case VCM_DO:
607         switch (self.waterlevel)
608         {
609         case 0:
610             if (self.tur_dist_enemy > 500)
611                 self.animflag = ANIM_RUN;
612             else
613                 self.animflag = ANIM_WALK;
614         case 1:
615         case 2:
616             if (self.animflag != ANIM_SWIM)
617                 self.animflag = ANIM_WALK;
618             else
619                 self.animflag = ANIM_SWIM;
620             break;
621         case 3:
622             self.animflag = ANIM_SWIM;
623         }
624
625         self.moveto = self.enemy.origin;
626         self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
627
628         return VS_CALL_YES_DOING;
629     }
630
631     return VS_CALL_YES_DONE;
632 }
633
634 float walker_moveverb_idle_pause(float eval)
635 {
636     switch (eval)
637     {
638     case VCM_EVAL:
639
640         if (self.animflag == ANIM_MEELE)
641             return VS_CALL_NO;
642
643         return verb.verb_static_value;
644
645     case VCM_DO:
646
647         self.moveto   = self.origin;
648         self.steerto  = v_forward;
649         self.animflag = ANIM_NO;
650
651         return VS_CALL_YES_DOING;
652     }
653
654     return VS_CALL_YES_DONE;
655 }
656
657 float walker_moveverb_idle_roam(float eval)
658 {
659     switch (eval)
660     {
661     case VCM_EVAL:
662
663         if (self.animflag == ANIM_MEELE)
664             return VS_CALL_NO;
665
666         return verb.verb_static_value;
667
668     case VCM_DO:
669         if(verb.wait < time)
670         {
671             trace_fraction = 0;
672             while(trace_fraction != 1.0)
673             {
674                 self.moveto = self.origin + (v_forward * 256);
675                 self.moveto += v_right * (random() * 256);
676                 self.moveto -= v_right * (random() * 256);
677
678                 tracebox(self.origin+'0 0 64',self.mins,self.maxs,self.moveto + '0 0 64',MOVE_NORMAL,self);
679             }
680             verb.wait = time + 10;
681         }
682         else
683         {
684             if(verb.wait - time < 9)
685                 if(vlen(self.moveto - self.origin) < 32)
686                 {
687                     verbstack_push(self.walker_verbs_move, walker_moveverb_idle_pause,   WVM_IDLE + WVM_IDLE_UP, random() * (verb.wait - time), self);
688                     self.animflag = ANIM_NO;
689                     return VS_CALL_REMOVE;
690                 }
691         }
692
693         self.steerto = steerlib_attract(self.moveto,256);
694         te_lightning1(self,self.origin + '0 0 64',self.moveto + '0 0 64');
695
696
697
698         switch (self.waterlevel)
699         {
700         case 0:
701             self.animflag = ANIM_ROAM;
702         case 1:
703         case 2:
704             if (self.animflag != ANIM_SWIM)
705                 self.animflag = ANIM_ROAM;
706
707             break;
708         case 3:
709             self.animflag = ANIM_SWIM;
710         }
711
712         return VS_CALL_YES_DOING;
713     }
714
715     return VS_CALL_YES_DONE;
716 }
717
718 float walker_moveverb_idle(float eval)
719 {
720     switch (eval)
721     {
722     case VCM_EVAL:
723
724         if (self.animflag == ANIM_MEELE)
725             return VS_CALL_NO;
726
727         return verb.verb_static_value;
728
729     case VCM_DO:
730
731         //if (random() < 0.5)
732             verbstack_push(self.walker_verbs_move, walker_moveverb_idle_pause,   WVM_IDLE + WVM_IDLE_UP, random() * 5, self);
733         //else
734         //    verbstack_push(self.walker_verbs_move, walker_moveverb_idle_roam,   WVM_IDLE + WVM_IDLE_UP,  random() * 15);
735
736         return VS_CALL_YES_DOING;
737     }
738
739     return VS_CALL_YES_DONE;
740 }
741
742 float walker_attackverb_meele(float eval)
743 {
744     switch (eval)
745     {
746     case VCM_EVAL:
747
748         vector wish_angle;
749
750         if (cvar("g_turrets_nofire"))
751             return VS_CALL_NO;
752
753         if (self.animflag == ANIM_SWIM || self.animflag == ANIM_MEELE)
754             return VS_CALL_NO;
755
756         if (!self.enemy)
757             return VS_CALL_NO;
758
759         wish_angle = angleofs(self,self.enemy);
760
761         if (self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_meele_range"))
762             if (fabs(wish_angle_y) < 15)
763                 return verb.verb_static_value;
764
765         return VS_CALL_NO;
766
767     case VCM_DO:
768
769         self.moveto   = self.enemy.origin;
770         self.steerto  = steerlib_attract2(self.moveto,0.5,500,0.95);
771         self.animflag = ANIM_MEELE;
772
773         return VS_CALL_YES_DOING;
774     }
775
776     return VS_CALL_YES_DONE;
777 }
778
779 float walker_attackverb_rockets(float eval)
780 {
781     switch (eval)
782     {
783     case VCM_EVAL:
784         if (self.tur_head.attack_finished_single > time)
785             return VS_CALL_NO;
786
787         if not(self.enemy)
788             return VS_CALL_NO;
789
790         if (cvar("g_turrets_nofire"))
791             return VS_CALL_NO;
792
793         if (self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_rockets_range_min"))
794             return VS_CALL_NO;
795
796         if (self.tur_dist_enemy > cvar("g_turrets_unit_walker_std_rockets_range"))
797             return VS_CALL_NO;
798
799         return verb.verb_static_value;
800
801     case VCM_DO:
802
803         entity rv;
804
805         rv           = spawn();
806         rv.think     = rv_think;
807         rv.nextthink = time;
808         rv.cnt       = 4;
809         rv.owner     = self;
810
811         self.tur_head.attack_finished_single = time + cvar("g_turrets_unit_walker_std_rocket_refire");
812
813         return VS_CALL_YES_DONE;
814     }
815
816     return VS_CALL_YES_DONE;
817 }
818
819 void walker_postthink()
820 {
821
822     self.angles_x *= -1;
823     makevectors(self.angles);
824     self.angles_x *= -1;
825
826     verbstack_pop(self.walker_verbs_attack);
827     verbstack_pop(self.walker_verbs_move);
828
829     walker_animate();
830 }
831
832 void walker_attack()
833 {
834     entity flash;
835
836     //w_deathtypestring = "was miniguned";
837     sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
838     fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET, 0, 1, cvar("g_balance_uzi_bulletconstant"));
839     if (self.uzi_bulletcounter == 2)
840     {
841
842         flash = spawn();
843
844         setmodel(flash, "models/uziflash.md3");
845         setattachment(flash, self.tur_head, "tag_fire");
846
847         flash.scale     = 3;
848         flash.think     = W_Uzi_Flash_Go;
849         flash.nextthink = time + 0.02;
850         flash.frame     = 2;
851         flash.angles_z  = flash.v_angle_z + random() * 180;
852         flash.alpha     = 1;
853         flash.effects   = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
854
855         self.uzi_bulletcounter = self.uzi_bulletcounter = 0;
856     }
857
858     self.uzi_bulletcounter = self.uzi_bulletcounter + 1;
859     self.tur_head.frame    = self.tur_head.frame + 1;
860 }
861
862
863 void walker_respawnhook()
864 {
865     vector vtmp;
866     entity e;
867
868     self.origin = self.wkr_spawn.origin;
869     //self.wkr_props.solid = SOLID_BBOX;
870     //self.wkr_props.alpha = 1;
871
872     self.angles = self.wkr_spawn.angles;
873     vtmp = self.wkr_spawn.origin;
874     vtmp_z += self.wkr_spawn.maxs_z;
875     setorigin(self,vtmp);
876
877     if (self.target != "")
878     {
879         e = find(world,targetname,self.target);
880         if (!e)
881         {
882             dprint("Warning! initital waypoint for Walker does NOT exsist!\n");
883             self.target = "";
884         }
885
886         if (e.classname != "turret_checkpoint")
887             dprint("Warning: not a turrret path\n");
888         else
889         {
890             self.pathcurrent = WALKER_PATH(self.origin,e.origin);
891             self.pathgoal = e;
892         }
893     }
894 }
895 void walker_diehook()
896 {
897     turret_trowgib2(self.origin,self.velocity + v_up * 200,'-0.6 -0.2 -02',self,time + random() * 1);
898     turret_trowgib2(self.origin + '0 0 64',self.velocity + v_forward * 150 + v_up * 150,'-0.2 -0.2 -02',self.tur_head,time + random() * 2 + 3);
899
900     if (self.pathcurrent)
901         pathlib_deletepath(self.pathcurrent.owner);
902
903     self.pathcurrent = world;
904
905     if (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
906     {
907         remove(self.wkr_spawn);
908
909         verbstack_flush(self.walker_verbs_move);
910         verbstack_flush(self.walker_verbs_attack);
911         verbstack_flush(self.walker_verbs_idle);
912
913         remove(self.walker_verbs_move);
914         remove(self.walker_verbs_attack);
915         remove(self.walker_verbs_idle);
916     }
917
918 }
919
920 void turret_walker_dinit()
921 {
922
923     entity e;
924
925     if (self.netname == "")      self.netname     = "Walker Turret";
926     self.wkr_spawn = spawn();
927
928     self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
929     self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_HEADATTACHED;
930     self.aim_flags = TFL_AIM_LEAD;
931
932     if (cvar("g_antilag_bullets"))
933         self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN;
934     else
935         self.aim_flags      |= TFL_AIM_SHOTTIMECOMPENSATE;
936
937
938     self.turret_respawnhook = walker_respawnhook;
939     self.turret_diehook = walker_diehook;
940
941     self.ticrate = 0.05;
942     if (turret_stdproc_init("walker_std",0) == 0)
943     {
944         remove(self);
945         return;
946     }
947
948     self.walker_verbs_move   = spawn();
949     self.walker_verbs_attack = spawn();
950     self.walker_verbs_idle   = spawn();
951
952     verbstack_push(self.walker_verbs_move, walker_moveverb_idle,   WVM_IDLE,  0, self);
953     verbstack_push(self.walker_verbs_move, walker_moveverb_enemy,  WVM_ENEMY, 0, self);
954     verbstack_push(self.walker_verbs_move, walker_moveverb_path,   WVM_PATH,  0, self);
955
956     verbstack_push(self.walker_verbs_attack, walker_attackverb_meele,   WVA_MEELE,  0, self);
957     verbstack_push(self.walker_verbs_attack, walker_attackverb_rockets, WVA_ROCKET, 0, self);
958
959     self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
960
961     self.target_select_flags   = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
962     self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
963
964     self.iscreature = TRUE;
965     self.movetype   = MOVETYPE_WALK;
966     self.solid      = SOLID_SLIDEBOX;
967     self.takedamage = DAMAGE_AIM;
968
969     setmodel(self,"models/turrets/walker_body.md3");
970     setmodel(self.tur_head,"models/turrets/walker_head_minigun.md3");
971     setmodel(self.wkr_spawn,"models/turrets/walker_spawn.md3");
972
973     setattachment(self.tur_head,self,"tag_head");
974
975     self.wkr_spawn.angles   = self.angles;
976     self.wkr_spawn.solid    = SOLID_NOT;
977
978     traceline(self.origin + '0 0 16', self.origin - '0 0 10000', MOVE_WORLDONLY, self);
979     setorigin(self.wkr_spawn,trace_endpos + '0 0 4');
980     setorigin(self,self.wkr_spawn.origin);
981
982     setsize(self,WALKER_MIN,WALKER_MAX);
983
984     self.idle_aim = '0 0 0';
985     self.turret_firecheckfunc = walker_firecheck;
986     self.turret_firefunc      = walker_attack;
987     self.turret_postthink     = walker_postthink;
988
989     if (self.target != "")
990     {
991         e = find(world,targetname,self.target);
992         if (!e)
993         {
994             dprint("Initital waypoint for walker does NOT exsist, fix your map!\n");
995             self.target = "";
996         }
997
998         if (e.classname != "turret_checkpoint")
999             dprint("Warning: not a turrret path\n");
1000         else
1001         {
1002             self.pathcurrent = WALKER_PATH(self.origin,e.origin);
1003             self.pathgoal = e;
1004         }
1005     }
1006 }
1007
1008
1009 void spawnfunc_turret_walker()
1010 {
1011     g_turrets_common_precash();
1012
1013     precache_model ("models/turrets/walker_head_minigun.md3");
1014     precache_model ("models/turrets/walker_body.md3");
1015     precache_model ("models/turrets/walker_props.md3");
1016     precache_model ("models/turrets/walker_spawn.md3");
1017     precache_model ( "models/turrets/rocket.md3");
1018     precache_sound ( "weapons/rocket_impact.wav" );
1019
1020     self.think = turret_walker_dinit;
1021     self.nextthink = time + 0.5;
1022 }