5 #define ANIM_STRAFE_L 4
6 #define ANIM_STRAFE_R 5
16 #define WALKER_MIN '-70 -70 0'
17 #define WALKER_MAX '70 70 95'
19 #define WALKER_PATH(s,e) pathlib_astar(s,e)
21 float walker_firecheck()
23 if (self.animflag == ANIM_MEELE)
26 return turret_stdproc_firecheck();
29 void walker_meele_do_dmg()
34 makevectors(self.angles);
35 where = self.origin + v_forward * 128;
37 e = findradius(where,32);
40 if (turret_validate_target(self,e,self.target_validate_flags))
41 if (e != self && e.owner != self)
42 Damage(e, self, self, autocvar_g_turrets_unit_walker_std_meele_dmg ,DEATH_TURRET,'0 0 0', v_forward * autocvar_g_turrets_unit_walker_std_meele_force);
47 void walker_setnoanim()
49 turrets_setframe(ANIM_NO, FALSE);
50 self.animflag = self.owner.frame;
58 real_angle = vectoangles(self.steerto) - self.angles;
61 if (self.tur_head.frame != 0)
62 self.tur_head.frame = self.tur_head.frame + 1;
64 if (self.tur_head.frame > 12)
65 self.tur_head.frame = 0;
67 switch (self.animflag)
71 turrets_setframe(0, FALSE);
72 movelib_beak_simple(autocvar_g_turrets_unit_walker_speed_stop);
77 if ((self.frame < 5) || (self.frame > 25))
80 self.frame = self.frame -1;
81 movelib_move_simple(v_forward * -1, autocvar_g_turrets_unit_walker_speed_walk, 0.6);
90 self.angles_y += bound(-15, shortangle_f(real_angle_y, self.angles_y), 15);
91 movelib_beak_simple(autocvar_g_turrets_unit_walker_speed_stop);
95 self.angles_y += bound(-10, shortangle_f(real_angle_y, self.angles_y), 10);
96 movelib_move_simple(v_forward, autocvar_g_turrets_unit_walker_speed_walk, 0.6);
100 self.angles_y += bound(-5, shortangle_f(real_angle_y, self.angles_y), 5);
101 movelib_move_simple(v_forward, autocvar_g_turrets_unit_walker_speed_run, 0.6);
105 self.angles_y += bound(-2.5, shortangle_f(real_angle_y, self.angles_y), 2.5);
106 movelib_move_simple(v_right * -1, autocvar_g_turrets_unit_walker_speed_walk, 0.8);
110 self.angles_y += bound(-2.5, shortangle_f(real_angle_y, self.angles_y), 2.5);
111 movelib_move_simple(v_right, autocvar_g_turrets_unit_walker_speed_walk, 0.8);
115 self.velocity += '0 0 1' * autocvar_g_turrets_unit_walker_speed_jump;
122 if(self.frame != ANIM_PAIN)
123 defer(0.25, walker_setnoanim);
128 if(self.frame != ANIM_MEELE)
130 defer(0.41, walker_setnoanim);
131 defer(0.21, walker_meele_do_dmg);
134 movelib_beak_simple(autocvar_g_turrets_unit_walker_speed_stop);
138 self.angles_y += bound(-10, shortangle_f(real_angle_y, self.angles_y), 10);
139 self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
140 movelib_move_simple(v_forward, autocvar_g_turrets_unit_walker_speed_swim, 0.3);
141 vz = self.velocity_z + sin(time * 4) * 8;
145 self.angles_y += bound(-5, shortangle_f(real_angle_y, self.angles_y), 5);
146 movelib_move_simple(v_forward ,autocvar_g_turrets_unit_walker_speed_roam, 0.5);
151 self.velocity_z = vz;
153 if (self.flags & FL_ONGROUND)
154 movelib_groundalign4point(300, 100, 0.25);
159 void walker_rocket_explode()
163 if (self.event_damage != SUB_Null)
165 self.event_damage = SUB_Null;
166 self.think = walker_rocket_explode;
167 self.nextthink = time;
171 sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
172 org2 = findbetterlocation (self.origin, 16);
174 pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
175 RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, world,autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET, world);
180 void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
182 self.health = self.health - damage;
183 self.velocity = self.velocity + vforce;
184 if (self.health <= 0)
185 walker_rocket_explode();
188 #define WALKER_ROCKET_MOVE movelib_move_simple(newdir, autocvar_g_turrets_unit_walker_std_rocket_speed, autocvar_g_turrets_unit_walker_std_rocket_turnrate); UpdateCSQCProjectile(self)
189 void walker_rocket_loop();
190 void walker_rocket_think()
197 self.nextthink = time;
199 edist = vlen(self.enemy.origin - self.origin);
201 // Simulate crude guidance
205 self.tur_shotorg = randomvec() * min(edist,64);
207 self.tur_shotorg = randomvec() * min(edist,256);
209 self.cnt = time + 0.5;
213 self.tur_shotorg = '0 0 0';
216 if (self.tur_health < time)
218 self.think = walker_rocket_explode;
219 self.nextthink = time;
223 if (self.shot_dmg != 1337)
226 walker_rocket_loop();
230 m_speed = vlen(self.velocity);
232 // Enemy dead? just keep on the current heading then.
233 if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
235 // Make sure we dont return to tracking a respawned entity
241 itime = max(edist / m_speed,1);
242 newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
246 newdir = normalize(self.velocity);
252 void walker_rocket_loop3()
255 self.nextthink = time;
257 if (self.tur_health < time)
259 self.think = walker_rocket_explode;
263 if (vlen(self.origin - self.tur_shotorg) < 100 )
265 self.think = walker_rocket_think;
269 newdir = steerlib_pull(self.tur_shotorg);
272 self.angles = vectoangles(self.velocity);
275 void walker_rocket_loop2()
279 self.nextthink = time;
281 if (self.tur_health < time)
283 self.think = walker_rocket_explode;
287 if (vlen(self.origin - self.tur_shotorg) < 100 )
289 self.tur_shotorg = self.origin - '0 0 200';
290 self.think = walker_rocket_loop3;
294 newdir = steerlib_pull(self.tur_shotorg);
298 void walker_rocket_loop()
300 self.nextthink = time;
301 self.tur_shotorg = self.origin + '0 0 300';
302 self.think = walker_rocket_loop2;
303 self.shot_dmg = 1337;
306 void walker_fire_rocket(vector org)
312 //self.angles_x *= -1;
313 fixedmakevectors(self.angles);
314 //self.angles_x *= -1;
319 setorigin(rocket, org);
321 sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
322 setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
324 rocket.classname = "walker_rocket";
327 rocket.bot_dodge = TRUE;
328 rocket.bot_dodgerating = 50;
330 rocket.takedamage = DAMAGE_YES;
332 rocket.damageforcescale = 2;
334 rocket.tur_shotorg = randomvec() * 512;
335 rocket.cnt = time + 1;
336 rocket.enemy = self.enemy;
339 rocket.think = walker_rocket_loop;
341 rocket.think = walker_rocket_think;
343 rocket.event_damage = walker_rocket_damage;
345 rocket.nextthink = time;// + 0.25;
346 rocket.movetype = MOVETYPE_FLY;
347 rocket.velocity = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * autocvar_g_turrets_unit_walker_std_rocket_speed;
348 rocket.angles = vectoangles(rocket.velocity);
349 rocket.touch = walker_rocket_explode;
350 rocket.flags = FL_PROJECTILE;
351 rocket.solid = SOLID_BBOX;
352 rocket.tur_health = time + 9;
354 CSQCProjectile(rocket, FALSE, PROJECTILE_ROCKET, FALSE); // no culling, has fly sound
363 if (self.owner.deadflag != DEAD_NO)
369 self.cnt = self.cnt -1;
378 f = gettagindex(self.owner,"tag_rocket01");
380 f = gettagindex(self.owner,"tag_rocket02");
382 org = gettaginfo(self.owner,f);
384 self.nextthink = time + 0.2;
387 walker_fire_rocket(org);
391 void walker_move_path()
393 // Are we close enougth to a path node to switch to the next?
394 if (vlen(self.origin - self.pathcurrent.origin) < 64)
395 if (self.pathcurrent.path_next == world)
397 // Path endpoint reached
398 pathlib_deletepath(self.pathcurrent.owner);
399 self.pathcurrent = world;
403 if (self.pathgoal.use)
406 if (self.pathgoal.enemy)
408 self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
409 self.pathgoal = self.pathgoal.enemy;
413 self.pathgoal = world;
416 self.pathcurrent = self.pathcurrent.path_next;
418 switch (self.waterlevel)
421 self.animflag = ANIM_WALK;
424 if (self.animflag == ANIM_WALK)
425 self.animflag = ANIM_WALK;
427 self.animflag = ANIM_SWIM;
430 self.animflag = ANIM_SWIM;
433 self.moveto = self.pathcurrent.origin;
434 self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
438 .vector enemy_last_loc;
439 void walker_move_enemy()
441 switch (self.waterlevel)
444 if (self.tur_dist_enemy > 500)
445 self.animflag = ANIM_RUN;
447 self.animflag = ANIM_WALK;
450 if (self.animflag != ANIM_SWIM)
451 self.animflag = ANIM_WALK;
453 self.animflag = ANIM_SWIM;
456 self.animflag = ANIM_SWIM;
459 self.moveto = self.enemy.origin;
460 self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
461 self.enemy_last_loc = self.enemy.origin;
465 void walker_move_idle_pause()
467 self.moveto = self.origin;
468 self.steerto = v_forward;
469 self.animflag = ANIM_NO;
472 void walker_move_idle_roam()
476 void walker_move_idle()
480 float walker_attack_meele()
484 if (self.animflag == ANIM_SWIM || self.animflag == ANIM_MEELE)
487 wish_angle = angleofs(self, self.enemy);
489 if (self.tur_dist_enemy > autocvar_g_turrets_unit_walker_std_meele_range)
492 if (fabs(wish_angle_y) > 15)
495 self.moveto = self.enemy.origin;
496 self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
497 self.animflag = ANIM_MEELE;
502 float walker_attack_rockets()
504 if (self.tur_head.attack_finished_single > time)
507 if (self.tur_dist_enemy < autocvar_g_turrets_unit_walker_std_rockets_range_min)
510 if (self.tur_dist_enemy > autocvar_g_turrets_unit_walker_std_rockets_range)
521 self.tur_head.attack_finished_single = time + autocvar_g_turrets_unit_walker_std_rocket_refire;
526 void walker_postthink()
528 fixedmakevectors(self.angles);
530 if ((self.spawnflags & TSF_NO_PATHBREAK) && self.pathcurrent)
532 else if (self.enemy == world)
537 walker_move_idle_pause();
541 if not (self.animflag == ANIM_MEELE)
542 if not (walker_attack_rockets())
543 walker_attack_meele();
545 if not (self.animflag == ANIM_MEELE)
551 if(self.origin != self.oldorigin)
552 self.SendFlags |= TNSF_MOVE;
554 self.oldorigin = self.origin;
555 turrets_setframe(self.animflag, FALSE);
561 sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
562 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, autocvar_g_balance_uzi_bulletconstant);
563 endFireBallisticBullet();
564 pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
566 self.tur_head.frame = self.tur_head.frame + 1;
570 void walker_respawnhook()
574 // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
575 if(self.movetype != MOVETYPE_WALK)
578 setorigin(self, self.pos1);
579 self.angles = self.pos2;
581 if (self.target != "")
583 e = find(world,targetname,self.target);
586 dprint("Warning! initital waypoint for Walker does NOT exsist!\n");
590 if (e.classname != "turret_checkpoint")
591 dprint("Warning: not a turrret path\n");
594 self.pathcurrent = WALKER_PATH(self.origin,e.origin);
598 self.colormod = randomvec() * 5;
601 void walker_diehook()
603 if (self.pathcurrent)
604 pathlib_deletepath(self.pathcurrent.owner);
606 self.pathcurrent = world;
609 void turret_walker_dinit()
614 if (self.netname == "") self.netname = "Walker Turret";
616 self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
617 self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE ;
618 self.aim_flags = TFL_AIM_LEAD;
620 if (autocvar_g_antilag_bullets)
621 self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN;
623 self.aim_flags |= TFL_AIM_SHOTTIMECOMPENSATE;
626 self.turret_respawnhook = walker_respawnhook;
627 self.turret_diehook = walker_diehook;
630 if (turret_stdproc_init("walker_std", "models/turrets/walker_body.md3", "models/turrets/walker_head_minigun.md3", TID_WALKER) == 0)
636 self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
637 self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
638 self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
640 self.iscreature = TRUE;
641 self.movetype = MOVETYPE_WALK;
642 self.solid = SOLID_SLIDEBOX;
643 self.takedamage = DAMAGE_AIM;
646 setsize(self, WALKER_MIN, WALKER_MAX);
648 setorigin(self, self.origin);
649 tracebox(self.origin + '0 0 128', self.mins,self.maxs,self.origin - '0 0 10000', MOVE_NORMAL, self);
650 setorigin(self, trace_endpos + '0 0 4');
651 self.pos1 = self.origin;
652 self.pos2 = self.angles;
654 self.idle_aim = '0 0 0';
655 self.turret_firecheckfunc = walker_firecheck;
656 self.turret_firefunc = walker_attack;
657 self.turret_postthink = walker_postthink;
659 if (self.target != "")
661 e = find(world,targetname,self.target);
664 dprint("Initital waypoint for walker does NOT exsist, fix your map!\n");
668 if (e.classname != "turret_checkpoint")
669 dprint("Warning: not a turrret path\n");
672 self.pathcurrent = WALKER_PATH(self.origin,e.origin);
679 void spawnfunc_turret_walker()
681 g_turrets_common_precash();
683 precache_model ("models/turrets/walker_head_minigun.md3");
684 precache_model ("models/turrets/walker_body.md3");
685 precache_model ( "models/turrets/rocket.md3");
686 precache_sound ( "weapons/rocket_impact.wav" );
688 self.think = turret_walker_dinit;
689 self.nextthink = time + 0.5;