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