1 //#define rocket_rack tur_head.enemy
\r
6 #define ANIM_STRAFE_L 2
\r
7 #define ANIM_STRAFE_R 3
\r
12 #define ANIM_MEELE 7
\r
19 #define WALKER_MIN '-70 -70 5'
\r
20 #define WALKER_MAX '70 70 70'
\r
23 .entity goalcurrent, goalstack01, goalstack02, goalstack03;
\r
24 .entity goalstack04, goalstack05, goalstack06, goalstack07;
\r
25 .entity goalstack08, goalstack09, goalstack10, goalstack11;
\r
26 .entity goalstack12, goalstack13, goalstack14, goalstack15;
\r
27 .entity goalstack16, goalstack17, goalstack18, goalstack19;
\r
28 .entity goalstack20, goalstack21, goalstack22, goalstack23;
\r
29 .entity goalstack24, goalstack25, goalstack26, goalstack27;
\r
30 .entity goalstack28, goalstack29, goalstack30, goalstack31;
\r
34 float walker_firecheck()
\r
36 return turret_stdproc_firecheck();
\r
39 void walker_meele_do_dmg()
\r
43 makevectors(self.angles);
\r
44 where = self.origin + v_forward * 128;
\r
46 e = findradius(where,128);
\r
49 if (turret_validate_target(self,e,self.target_validate_flags))
\r
52 //bprint(self.netname, " is meele hitting ",e.netname,"\n");
\r
53 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
60 void walker_animate()
\r
63 switch (self.animflag)
\r
71 self.frame = self.frame + 1;
\r
72 if (self.frame > 25)
\r
79 self.frame = self.frame + 2;
\r
80 if (self.frame > 25)
\r
85 if (self.frame < 35) self.frame = 35;
\r
86 self.frame = self.frame + 1;
\r
87 if (self.frame > 55) self.frame = 35;
\r
91 if (self.frame < 65) self.frame = 65;
\r
92 self.frame = self.frame + 1;
\r
93 if (self.frame > 85) self.frame = 65;
\r
97 if (self.frame < 95) self.frame = 95;
\r
98 if (self.frame > 100)
\r
99 self.frame = self.frame + 1;
\r
104 if (self.frame < 100) self.frame = 100;
\r
105 self.frame = self.frame + 1;
\r
106 if (self.frame > 107)
\r
107 self.animflag = ANIM_NO;
\r
111 if (self.frame < 60) self.frame = 90;
\r
112 self.frame = self.frame + 1;
\r
113 if (self.frame > 95)
\r
114 self.animflag = ANIM_NO;
\r
118 if (self.frame < 123) self.frame = 123;
\r
119 self.frame = self.frame + 1;
\r
121 if (self.frame == 133)
\r
122 walker_meele_do_dmg();
\r
124 if (self.frame > 140)
\r
125 self.animflag = ANIM_NO;
\r
131 void walker_rocket_explode()
\r
135 if(self.event_damage != SUB_Null)
\r
137 self.event_damage = SUB_Null;
\r
138 self.think = walker_rocket_explode;
\r
139 self.nextthink = time;
\r
143 sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
\r
144 org2 = findbetterlocation (self.origin, 16);
\r
146 pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
\r
148 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
153 void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
\r
155 self.health = self.health - damage;
\r
156 self.velocity = self.velocity + vforce;
\r
157 if (self.health <= 0) walker_rocket_explode();
\r
160 //#define WALKER_ROCKET_MOVE movelib_move(newdir * 275,900,0.1,10)
\r
161 #define WALKER_ROCKET_MOVE movelib_move_simple(newdir,1000,cvar("g_turrets_unit_walker_std_rocket_tunrate")); UpdateCSQCProjectile(self)
\r
162 void walker_rocket_loop();
\r
163 void walker_rocket_think()
\r
165 vector olddir,newdir;
\r
170 self.nextthink = time + 0.1;
\r
172 olddir = normalize(self.velocity);
\r
173 edist = vlen(self.enemy.origin - self.origin);
\r
175 // Simulate crude guidance
\r
176 if (self.cnt < time)
\r
179 self.tur_shotorg = randomvec() * min(edist,64);
\r
181 self.tur_shotorg = randomvec() * min(edist,256);
\r
182 self.cnt = time + 0.5;
\r
185 self.tur_shotorg = '0 0 0';
\r
188 if (self.tur_health < time)
\r
190 self.think = walker_rocket_explode;
\r
191 self.nextthink = time;
\r
195 if ((random() < 0.01) && (self.shot_dmg != 1337))
\r
197 walker_rocket_loop();
\r
201 olddir = normalize(self.velocity);
\r
203 m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
\r
205 // Enemy dead? just keep on the current heading then.
\r
206 if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
\r
209 // Make sure we dont return to tracking a respawned player
\r
210 self.enemy = world;
\r
213 self.angles = vectoangles(self.velocity);
\r
218 itime = max(edist / m_speed,1);
\r
219 newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
\r
226 WALKER_ROCKET_MOVE;
\r
230 self.angles = vectoangles(self.velocity);
\r
232 if (time + itime < time + 0.1)
\r
234 self.think = walker_rocket_explode;
\r
235 self.nextthink = time + itime;
\r
239 void walker_rocket_loop3()
\r
241 if (self.tur_health < time)
\r
243 self.think = walker_rocket_explode;
\r
244 self.nextthink = time;
\r
248 self.nextthink = time + 0.1;
\r
250 if (vlen(self.origin - self.tur_shotorg) < 128 )
\r
252 self.think = walker_rocket_think;
\r
258 newdir = steerlib_pull(self.tur_shotorg);
\r
259 WALKER_ROCKET_MOVE;
\r
261 self.angles = vectoangles(self.velocity);
\r
264 void walker_rocket_loop2()
\r
266 if (self.tur_health < time)
\r
268 self.think = walker_rocket_explode;
\r
269 self.nextthink = time;
\r
273 self.nextthink = time;
\r
275 if (vlen(self.origin - self.tur_shotorg) < 128 )
\r
277 self.tur_shotorg = self.origin - '0 0 200';
\r
278 self.think = walker_rocket_loop3;
\r
284 newdir = steerlib_pull(self.tur_shotorg);
\r
285 WALKER_ROCKET_MOVE;
\r
287 self.angles = vectoangles(self.velocity);
\r
291 void walker_rocket_loop()
\r
293 self.nextthink= time + 0;
\r
294 self.tur_shotorg = self.origin + '0 0 400';
\r
295 self.think = walker_rocket_loop2;
\r
296 self.shot_dmg = 1337;
\r
299 void walker_fire_rocket(vector org)
\r
305 //self.angles_x *= -1;
\r
306 makevectors(self.angles);
\r
307 //self.angles_x *= -1;
\r
310 setorigin(rocket, org);
\r
312 sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", VOL_BASE, ATTN_NORM);
\r
313 setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
\r
315 rocket.classname = "walker_rocket";
\r
316 rocket.owner = self;
\r
317 rocket.bot_dodge = TRUE;
\r
318 rocket.bot_dodgerating = 50;
\r
319 rocket.takedamage = DAMAGE_YES;
\r
321 rocket.damageforcescale = 2;
\r
322 rocket.health = 10;
\r
323 rocket.tur_shotorg = randomvec() * 512;
\r
324 rocket.cnt = time + 1;
\r
325 rocket.enemy = self.enemy;
\r
327 if (random() < 0.01)
\r
328 rocket.think = walker_rocket_loop;
\r
330 rocket.think = walker_rocket_think;
\r
332 rocket.event_damage = walker_rocket_damage;
\r
334 rocket.nextthink = time + 0.25;
\r
335 rocket.solid = SOLID_BBOX;
\r
336 rocket.movetype = MOVETYPE_FLYMISSILE;
\r
337 rocket.velocity = ((v_forward + v_up * 0.25) +(randomvec() * 0.1))* cvar("g_turrets_unit_walker_std_rocket_speed");
\r
338 rocket.angles = vectoangles(rocket.velocity);
\r
339 rocket.touch = walker_rocket_explode;
\r
340 rocket.flags = FL_PROJECTILE;
\r
341 rocket.solid = SOLID_BBOX;
\r
342 rocket.tur_health = time + 9;
\r
344 CSQCProjectile(rocket, TRUE, PROJECTILE_ROCKET, FALSE); // no cull, fly sound
\r
346 te_explosion (rocket.origin);
\r
355 #define s_accel2 16
\r
365 if(self.owner.deadflag != DEAD_NO)
\r
371 self.cnt = self.cnt -1;
\r
380 f = gettagindex(self.owner,"tag_rocket01");
\r
382 f = gettagindex(self.owner,"tag_rocket02");
\r
384 org = self.owner.origin + gettaginfo(self.owner,f);
\r
388 self.nextthink = time + 0.2;
\r
391 walker_fire_rocket(org);
\r
399 animation_set(self,5,25,40,AF_ENDCALLBACK,5);
\r
404 animation_set(self,5,25,20,AF_ENDCALLBACK,5);
\r
411 void set_acb(void() acb_func)
\r
413 self.animator_callback = acb_func;
\r
414 if(animation_query(self) != AS_RUNNING)
\r
416 bprint("Not running\n");
\r
421 if not(self.animator.anim_flags & AF_ENDCALLBACK)
\r
422 self.animator.anim_flags = self.animator.anim_flags | AF_ENDCALLBACK;
\r
427 void walker_postthink()
\r
434 //if (self.flags & FL_ONGROUND)
\r
435 //if (self.animflag != ANIM_MEELE)
\r
436 // self.animflag = ANIM_NO;
\r
438 if (self.tur_head.attack_finished_single < time)
\r
444 rv.think = rv_think;
\r
445 rv.nextthink = time;
\r
449 self.tur_head.attack_finished_single = time + cvar("g_turrets_unit_walker_std_rocket_refire");
\r
452 // Do we have a path?
\r
453 if (self.pathcurrent)
\r
455 //set_acb(acb_walk);
\r
456 self.animflag = ANIM_WALK;
\r
458 // Are we close enougth to a path node to switch to the next?
\r
459 if (vlen(self.origin - self.pathcurrent.origin) < 64)
\r
460 if (self.pathcurrent.path_next == world)
\r
462 // Path endpoint reached
\r
463 pathlib_deletepath(self.pathcurrent.owner);
\r
464 self.pathcurrent = world;
\r
468 if(self.pathgoal.use)
\r
469 self.pathgoal.use();
\r
471 if(self.pathgoal.enemy)
\r
473 self.pathcurrent = pathlib_makepath(self.pathgoal.origin,self.pathgoal.enemy.origin,PLF_GROUNDSNAP,1500,2,PT_QUICKBOX);
\r
474 self.pathgoal = self.pathgoal.enemy;
\r
478 self.pathgoal = world;
\r
481 self.pathcurrent = self.pathcurrent.path_next;
\r
483 steer = steerlib_attract2(self.pathcurrent.origin,0.5,2000,0.95);
\r
486 else // Roaming mode
\r
490 wish_angle = angleofs(self,self.enemy);
\r
491 steer = steerlib_pull(self.enemy.origin);
\r
493 if (self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_meele_range"))
\r
495 if (fabs(wish_angle_y) < 15)
\r
498 //set_acb(acb_meele);
\r
499 //walker_do_meele();
\r
500 self.animflag = ANIM_MEELE;
\r
506 if (fabs(wish_angle_y) < 15)
\r
508 //set_acb(acb_run);
\r
509 self.animflag = ANIM_RUN;
\r
512 else if (fabs(wish_angle_y) < 30)
\r
514 //set_acb(acb_walk);
\r
515 self.animflag = ANIM_WALK;
\r
520 //set_acb(acb_walk);
\r
521 self.animflag = ANIM_WALK;
\r
530 if(self.animflag != ANIM_MEELE)
\r
531 self.animflag = ANIM_NO;
\r
535 // Align the walker to the ground
\r
537 self.angles_x = self.angles_x * -1;
\r
538 makevectors(self.angles);
\r
539 self.angles_x = self.angles_x * -1;
\r
541 traceline(self.origin + '0 0 15', self.origin - '0 0 150' ,MOVE_WORLDONLY,self);
\r
542 wish_angle = (trace_endpos);
\r
543 traceline(self.origin + v_forward * 10 + '0 0 15', self.origin + v_forward * 10 - '0 0 150' ,MOVE_WORLDONLY,self);
\r
544 real_angle = vectoangles(normalize( trace_endpos - wish_angle));
\r
546 self.angles_x = real_angle_x;
\r
547 self.angles_z = real_angle_z;
\r
551 self.velocity = '0 0 0';
\r
552 //animator_remove(self);
\r
556 steer = steer * 0.5 + steerlib_traceavoid(0.3,256);
\r
558 vz = self.velocity_z;
\r
559 movelib_move_simple(steer * 200,vel,0.5);
\r
560 self.velocity_z = vz;
\r
562 wish_angle = vectoangles(self.velocity);
\r
564 real_angle = wish_angle - self.angles;
\r
566 real_angle_y = shortangle_f(real_angle_y,self.angles_y);
\r
568 self.angles_y = self.angles_y + bound(-5,real_angle_y,5);
\r
572 if (self.tur_head.frame != 0)
\r
573 self.tur_head.frame = self.tur_head.frame +1;
\r
575 if (self.tur_head.frame > 12)
\r
576 self.tur_head.frame = 0;
\r
581 void walker_attack()
\r
585 //turret_do_updates(self);
\r
587 self.tur_head.frame = self.tur_head.frame + 1;
\r
589 sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
\r
592 fireBullet (self.tur_shotorg_updated, self.tur_shotdir_updated,self.shot_spread, self.shot_dmg, self.shot_force, DEATH_TURRET, FALSE);
\r
594 te_smallflash(self.tur_shotorg_updated);
\r
596 if (!(self.uzi_bulletcounter & 3))
\r
599 trailparticles(self,particleeffectnum("EF_MGTURRETTRAIL"),self.tur_shotorg_updated,trace_endpos);
\r
600 // te_lightning1(self,self.tur_shotorg_updated,trace_endpos);
\r
602 setmodel(flash, "models/uziflash.md3"); // precision set below
\r
603 setattachment(flash, self.tur_head, "tag_fire");
\r
605 flash.think = W_Uzi_Flash_Go;
\r
606 flash.nextthink = time + 0.02;
\r
608 flash.angles_z = flash.v_angle_z + random() * 180;
\r
610 flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
\r
613 self.uzi_bulletcounter = self.uzi_bulletcounter + 1;
\r
617 void walker_respawnhook()
\r
622 //load_unit_settings(self.rocket_rack,"walker_std_rocket",1);
\r
624 self.origin = self.wkr_spawn.origin;
\r
625 self.wkr_props.solid = SOLID_BBOX;
\r
626 self.wkr_props.alpha = 1;
\r
628 self.angles = self.wkr_spawn.angles;
\r
629 vtmp = self.origin;
\r
630 vtmp_z +=self.wkr_spawn.origin_z + self.wkr_spawn.maxs_z;
\r
631 setorigin(self,vtmp);
\r
633 if (self.target != "")
\r
635 e = find(world,targetname,self.target);
\r
638 bprint("Warning! initital waypoint for Walker does NOT exsist!\n");
\r
642 if (e.classname != "turret_checkpoint")
\r
643 dprint("Warning: not a turrret path\n");
\r
646 self.pathcurrent = pathlib_makepath(self.origin,e.origin,PLF_GROUNDSNAP,500,2,PT_QUICKBOX);
\r
651 void walker_diehook()
\r
653 //animator_remove(self);
\r
655 if(self.pathcurrent)
\r
656 pathlib_deletepath(self.pathcurrent.owner);
\r
658 self.pathcurrent = world;
\r
660 self.wkr_props.solid = SOLID_NOT;
\r
661 self.wkr_props.alpha = -1;
\r
663 if(self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
\r
666 remove(self.wkr_props);
\r
667 //remove(self.rocket_rack);
\r
668 remove(self.wkr_spawn);
\r
673 //.string target_start;
\r
674 void turret_walker_dinit()
\r
679 if (self.netname == "") self.netname = "Walker Turret";
\r
682 self.wkr_props = spawn();
\r
683 self.wkr_spawn = spawn();
\r
685 self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
\r
686 self.turrcaps_flags = TFL_TURRCAPS_HITSCAN | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_ROAM | TFL_TURRCAPS_LINKED;
\r
687 self.aim_flags = TFL_AIM_LEAD | TFL_AIM_ZEASE;
\r
689 self.turret_respawnhook = walker_respawnhook;
\r
690 self.turret_diehook = walker_diehook;
\r
692 self.ticrate = 0.05;
\r
693 if (turret_stdproc_init("walker_std") == 0)
\r
698 self.damage_flags |= RFL_DMG_DEATH_NOGIBS;
\r
700 self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
\r
701 self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;// | TFL_TARGETSELECT_LOS;
\r
703 //self.flags = FL_CLIENT;
\r
704 self.iscreature = TRUE;
\r
705 self.movetype = MOVETYPE_WALK;
\r
706 self.solid = SOLID_SLIDEBOX;
\r
707 self.takedamage = DAMAGE_AIM;
\r
709 setmodel(self.wkr_props,"models/turrets/walker_props.md3");
\r
710 setmodel(self.wkr_spawn,"models/turrets/walker_spawn.md3");
\r
711 setorigin(self.wkr_spawn,self.origin);
\r
713 self.wkr_spawn.angles = self.angles;
\r
714 self.wkr_spawn.solid = SOLID_NOT;
\r
717 traceline(self.wkr_spawn.origin + '0 0 10', self.wkr_spawn.origin - '0 0 10000', MOVE_NOMONSTERS, self);
\r
718 setorigin(self.wkr_spawn,trace_endpos + '0 0 4');
\r
720 setmodel(self,"models/turrets/walker_body.md3");
\r
721 setmodel(self.tur_head,"models/turrets/walker_head_minigun.md3");
\r
723 setattachment(self.tur_head,self,"tag_head");
\r
724 setattachment(self.wkr_props,self,"tag_head");
\r
728 f = gettagindex(self.tur_head,"tag_fire");
\r
729 v = gettaginfo(self.tur_head,f);
\r
732 setsize(self,WALKER_MIN,WALKER_MAX);
\r
733 //setsize(self,'-70 -70 0','70 70 55');
\r
735 self.tur_shotorg = v;
\r
736 self.tur_aimorg = v;// + '0 0 10';
\r
738 self.idle_aim = '0 0 0';
\r
740 // self.v_home = self.origin;
\r
742 self.turret_firecheckfunc = walker_firecheck;
\r
744 // Our fire routine
\r
745 self.turret_firefunc = walker_attack;
\r
747 self.turret_postthink = walker_postthink;
\r
749 if (self.target != "")
\r
751 e = find(world,targetname,self.target);
\r
754 bprint("Warning! initital waypoint for Walker does NOT exsist!\n");
\r
758 if (e.classname != "turret_checkpoint")
\r
759 dprint("Warning: not a turrret path\n");
\r
762 self.pathcurrent = pathlib_makepath(self.origin,e.origin,PLF_GROUNDSNAP,500,2,PT_QUICKBOX);
\r
767 //self.solid = SOLID_NOT;
\r
772 void spawnfunc_turret_walker()
\r
774 precache_model ("models/turrets/walker_head_minigun.md3");
\r
775 precache_model ("models/turrets/walker_body.md3");
\r
776 precache_model ("models/turrets/walker_props.md3");
\r
777 precache_model ("models/turrets/walker_spawn.md3");
\r
778 precache_model ( "models/turrets/rocket.md3");
\r
780 self.think = turret_walker_dinit;
\r
781 self.nextthink = time + 0.5;
\r