4 #define ANIM_STRAFE_L 2
\r
5 #define ANIM_STRAFE_R 3
\r
10 #define ANIM_MEELE 7
\r
16 #define WALKER_MIN '-70 -70 5'
\r
17 #define WALKER_MAX '70 70 70'
\r
20 .entity goalcurrent, goalstack01, goalstack02, goalstack03;
\r
21 .entity goalstack04, goalstack05, goalstack06, goalstack07;
\r
22 .entity goalstack08, goalstack09, goalstack10, goalstack11;
\r
23 .entity goalstack12, goalstack13, goalstack14, goalstack15;
\r
24 .entity goalstack16, goalstack17, goalstack18, goalstack19;
\r
25 .entity goalstack20, goalstack21, goalstack22, goalstack23;
\r
26 .entity goalstack24, goalstack25, goalstack26, goalstack27;
\r
27 .entity goalstack28, goalstack29, goalstack30, goalstack31;
\r
30 float walker_firecheck()
\r
32 if (!turret_stdproc_firecheck()) return 0;
\r
33 //if(self.tur_cannon.frame != 0) return 0;
\r
35 //if(self.walking == 1) self.walking = 2;
\r
36 //if(self.walking != 0)
\r
42 void walker_meele_dmg()
\r
47 makevectors(self.angles);
\r
48 where = self.origin + v_forward * 128;
\r
50 e = findradius(where,80);
\r
53 if(turret_validate_target(self,e,self.target_validate_flags))
\r
55 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
61 void walker_animate()
\r
64 if(self.tur_head.frame != 0)
\r
65 self.tur_head.frame = self.tur_head.frame +1;
\r
67 if(self.tur_head.frame > 12)
\r
68 self.tur_head.frame = 0;
\r
71 switch(self.animflag)
\r
74 //if(self.frame != 0)
\r
79 self.frame = self.frame + 1;
\r
85 self.frame = self.frame + 2;
\r
91 if(self.frame < 35) self.frame = 35;
\r
92 self.frame = self.frame + 1;
\r
93 if(self.frame > 55) self.frame = 35;
\r
97 if(self.frame < 65) self.frame = 65;
\r
98 self.frame = self.frame + 1;
\r
99 if(self.frame > 85) self.frame = 65;
\r
103 if(self.frame < 95) self.frame = 95;
\r
104 if(self.frame > 100)
\r
105 self.frame = self.frame + 1;
\r
110 if(self.frame < 100) self.frame = 100;
\r
111 self.frame = self.frame + 1;
\r
112 if(self.frame > 107)
\r
113 self.animflag = ANIM_NO;
\r
117 if(self.frame < 90) self.frame = 90;
\r
118 self.frame = self.frame + 1;
\r
119 if(self.frame > 95)
\r
120 self.animflag = ANIM_NO;
\r
124 if(self.frame < 123) self.frame = 123;
\r
125 self.frame = self.frame + 1;
\r
127 if(self.frame == 133)
\r
128 walker_meele_dmg();
\r
130 if(self.frame > 140)
\r
131 self.animflag = ANIM_NO;
\r
140 void walker_rocket_explode()
\r
144 sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", 1, ATTN_NORM);
\r
145 org2 = findbetterlocation (self.origin, 16);
\r
147 WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
\r
148 WriteByte (MSG_BROADCAST, 78);
\r
149 WriteCoord (MSG_BROADCAST, org2_x);
\r
150 WriteCoord (MSG_BROADCAST, org2_y);
\r
151 WriteCoord (MSG_BROADCAST, org2_z);
\r
153 self.event_damage = SUB_Null;
\r
155 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
160 void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
\r
162 self.health = self.health - damage;
\r
163 self.velocity = self.velocity + vforce;
\r
164 if (self.health <= 0) walker_rocket_explode();
\r
169 g_turrets_unit_walker_std_rocket_refire
\r
170 g_turrets_unit_walker_std_rocket_dmg
\r
171 g_turrets_unit_walker_std_rocket_radius
\r
172 g_turrets_unit_walker_std_rocket_force
\r
173 g_turrets_unit_walker_std_rocket_tunrate
\r
174 g_turrets_unit_walker_std_rocket_speed
\r
175 g_turrets_unit_walker_std_rocket_speed_add
\r
178 void walker_rocket_loop();
\r
179 void walker_rocket_think()
\r
181 vector olddir,newdir;
\r
186 self.nextthink = time + 0.1;
\r
188 olddir = normalize(self.velocity);
\r
189 edist = vlen(self.enemy.origin - self.origin);
\r
191 // Simulate crudely guidance
\r
192 if(self.cnt < time)
\r
195 self.tur_shotorg = randomvec() * min(edist,64);
\r
197 self.tur_shotorg = randomvec() * min(edist,256);
\r
198 self.cnt = time + 0.5;
\r
201 self.tur_shotorg = '0 0 0';
\r
204 if (self.tur_health < time)
\r
206 self.think = walker_rocket_explode;
\r
207 self.nextthink = time;
\r
211 if((random() < 0.01) && (self.shot_dmg != 1337))
\r
213 walker_rocket_loop();
\r
217 olddir = normalize(self.velocity);
\r
220 m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
\r
222 // Enemy dead? just keep on the current heading then.
\r
223 if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
\r
226 // Make sure we dont return to tracking a respawned player
\r
227 self.enemy = world;
\r
230 self.angles = vectoangles(self.velocity);
\r
235 // Predict enemy position
\r
236 itime = max(edist / m_speed,1);
\r
237 newdir = normalize((self.enemy.origin + self.tur_shotorg) - self.origin);
\r
241 //pre_pos = self.origin + olddir;
\r
246 newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate"));
\r
248 self.velocity = newdir * m_speed;
\r
251 self.angles = vectoangles(self.velocity);
\r
253 if (time+itime < time+0.1)
\r
255 self.think = turret_hellion_missile_explode;
\r
256 self.nextthink = time + itime;
\r
260 void walker_rocket_loop3()
\r
262 self.nextthink = time + 0.1;
\r
263 if(vlen(self.origin - self.tur_shotorg) < 128 )
\r
265 self.think = walker_rocket_think;
\r
273 m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
\r
275 olddir = normalize(self.velocity);
\r
278 newdir = normalize(self.tur_shotorg - self.origin);
\r
280 newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate"));
\r
283 self.velocity = newdir * m_speed;
\r
284 self.angles = vectoangles(self.velocity);
\r
287 void walker_rocket_loop2()
\r
289 self.nextthink = time + 0;
\r
291 if(vlen(self.origin - self.tur_shotorg) < 128 )
\r
293 self.tur_shotorg = self.origin - '0 0 200';
\r
294 self.think = walker_rocket_loop3;
\r
302 m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
\r
304 olddir = normalize(self.velocity);
\r
306 newdir = normalize(self.tur_shotorg - self.origin);
\r
308 newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate"));
\r
310 self.velocity = newdir * m_speed;
\r
312 self.angles = vectoangles(self.velocity);
\r
316 void walker_rocket_loop()
\r
319 self.nextthink= time + 0;
\r
321 self.tur_shotorg = self.origin + '0 0 400';
\r
323 self.think = walker_rocket_loop2;
\r
325 self.shot_dmg = 1337;
\r
330 void walker_fire_rocket(vector org)
\r
336 //self.angles_x *= -1;
\r
337 makevectors(self.angles);
\r
338 //self.angles_x *= -1;
\r
341 setorigin(rocket, org);
\r
343 sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", 1, ATTN_NORM);
\r
344 sound (rocket, CHAN_PROJECTILE, "weapons/rocket_fly.wav", 0.4, ATTN_NORM);
\r
345 setmodel (rocket, "models/turrets/rocket.md3"); // precision set below
\r
346 setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
\r
348 rocket.classname = "walker_rocket";
\r
349 rocket.owner = self;
\r
350 rocket.bot_dodge = TRUE;
\r
351 rocket.bot_dodgerating = 50;
\r
352 rocket.takedamage = DAMAGE_YES;
\r
354 rocket.damageforcescale = 2;
\r
355 rocket.health = 10;
\r
356 rocket.tur_shotorg = randomvec() * 512;
\r
357 rocket.cnt = time + 1;
\r
358 rocket.enemy = self.enemy;
\r
360 if(random() < 0.01)
\r
361 rocket.think = walker_rocket_loop;
\r
363 rocket.think = walker_rocket_think;
\r
365 rocket.nextthink = time + 0.2;
\r
366 rocket.solid = SOLID_BBOX;
\r
367 rocket.movetype = MOVETYPE_FLYMISSILE;
\r
368 rocket.effects = EF_LOWPRECISION;
\r
369 rocket.velocity = ((v_forward + v_up * 0.5) +(randomvec() * 0.15))* cvar("g_turrets_unit_walker_std_rocket_speed");
\r
370 rocket.angles = vectoangles(rocket.velocity);
\r
371 rocket.touch = walker_rocket_explode;
\r
372 rocket.flags = FL_PROJECTILE;
\r
373 rocket.solid = SOLID_BBOX;
\r
374 rocket.tur_health = time + 9;
\r
376 te_explosion (rocket.origin);
\r
384 #define s_accel2 16
\r
392 self.cnt = self.cnt -1;
\r
400 f = gettagindex(self.owner,"tag_rocket01");
\r
402 f = gettagindex(self.owner,"tag_rocket02");
\r
404 org = self.owner.origin + gettaginfo(self.owner,f);
\r
407 self.nextthink = time + 0.2;
\r
410 walker_fire_rocket(org);
\r
413 void walker_postthink()
\r
421 if(self.flags & FL_ONGROUND)
\r
423 self.animflag = ANIM_NO;
\r
428 if(self.tur_head.attack_finished_single < time)
\r
432 rv.think = rv_think;
\r
433 rv.nextthink = time;
\r
437 self.tur_head.attack_finished_single = time + cvar("g_turrets_unit_walker_std_rocket_refire");
\r
442 if(self.goalcurrent)
\r
444 //if(self.enemy && (self.tur_dist_enemy < self.target_range_fire))
\r
445 // self.animflag = ANIM_TURN;
\r
448 if(vlen(self.origin - self.goalcurrent.origin) < 64)
\r
449 if(self.goalcurrent.goalcurrent == world)
\r
450 self.goalcurrent = world; // Path endpoint reached, go roaming.
\r
452 self.goalcurrent = self.goalcurrent.goalcurrent;
\r
454 self.animflag = ANIM_WALK;
\r
459 else // Roaming mode
\r
464 wish_angle = angleofs(self,self.enemy); //normalize(self.origin-self.enemy.origin);
\r
466 if(self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_meele_range"))
\r
469 if(fabs(wish_angle_y) < 15)
\r
470 self.animflag = ANIM_MEELE;
\r
474 if(fabs(wish_angle_y) < 15)
\r
475 self.animflag = ANIM_RUN;
\r
476 else if(fabs(wish_angle_y) < 30)
\r
477 self.animflag = ANIM_WALK;
\r
479 self.animflag = ANIM_TURN;
\r
484 self.animflag = ANIM_NO;
\r
490 s_speed = vlen(self.velocity);
\r
492 // Turn on the spot
\r
493 if (self.animflag == ANIM_TURN) {
\r
495 wish_angle = normalize(self.enemy.origin - self.origin);
\r
497 wish_angle = normalize(self.goalcurrent.origin - self.origin); wish_angle = vectoangles(wish_angle); // And make a angle
\r
499 real_angle = wish_angle - self.angles;
\r
501 if (real_angle_x < 0) real_angle_x += 360;
\r
502 if (real_angle_x > 180) real_angle_x -= 360;
\r
504 if (real_angle_y < 0) real_angle_y += 360;
\r
505 if (real_angle_y > 180) real_angle_y -= 360;
\r
507 turn_limit = cvar("g_turrets_unit_walker_turn_turnrate");
\r
508 // Convert from dgr/sec to dgr/tic
\r
509 turn_limit = turn_limit / (1 / self.ticrate);
\r
511 //real_angle_x = bound((-1 * turn_limit),real_angle_x, turn_limit);
\r
512 real_angle_y = bound((-1 * turn_limit),real_angle_y, turn_limit);
\r
514 self.angles_y = self.angles_y + real_angle_y;
\r
517 v_forward = normalize(self.enemy.origin - self.origin);
\r
519 v_forward = normalize(self.goalcurrent.origin - self.origin);
\r
521 makevectors(self.angles);
\r
523 if(s_speed > s_turn)
\r
524 self.velocity = (v_forward * max((s_speed - s_decel),s_turn));
\r
525 if(s_speed < s_turn)
\r
526 self.velocity = (v_forward * min((s_speed + s_accel1),s_turn));
\r
528 else if (self.animflag == ANIM_WALK) // Gg walking
\r
530 if(self.goalcurrent)
\r
531 wish_angle = normalize(self.goalcurrent.origin - self.origin);
\r
534 wish_angle = normalize(self.enemy.origin - self.origin);
\r
536 wish_angle = self.angles;
\r
539 wish_angle = vectoangles(wish_angle); // And make a angle
\r
540 real_angle = wish_angle - self.angles;
\r
542 if (real_angle_x < 0) real_angle_x += 360;
\r
543 if (real_angle_x > 180) real_angle_x -= 360;
\r
545 if (real_angle_y < 0) real_angle_y += 360;
\r
546 if (real_angle_y > 180) real_angle_y -= 360;
\r
548 turn_limit = cvar("g_turrets_unit_walker_walk_turnrate");
\r
549 // Convert from dgr/sec to dgr/tic
\r
550 turn_limit = turn_limit / (1 / self.ticrate);
\r
552 //real_angle_x = bound((-1 * turn_limit),real_angle_x, turn_limit);
\r
553 real_angle_y = bound((-1 * turn_limit),real_angle_y, turn_limit);
\r
555 self.angles_y = self.angles_y + real_angle_y;
\r
557 if(self.goalcurrent)
\r
558 v_forward = normalize(self.goalcurrent.origin - self.origin);
\r
561 v_forward = normalize(self.enemy.origin - self.origin);
\r
563 makevectors(self.angles);
\r
564 //self.velocity = v_forward * s_walk;
\r
566 //if(self.flags & FL_ONGROUND)
\r
568 if(s_speed > s_walk)
\r
569 self.velocity = (v_forward * max((s_speed - s_decel),s_walk));
\r
570 if(s_speed <= s_walk)
\r
571 self.velocity = (v_forward * min((s_speed + s_accel1),s_walk));
\r
576 else if (self.animflag == ANIM_RUN) // Move fast, turn slow
\r
578 if(self.goalcurrent)
\r
579 wish_angle = normalize(self.goalcurrent.origin - self.origin);
\r
582 wish_angle = normalize(self.enemy.origin - self.origin);
\r
584 wish_angle = self.angles;
\r
586 wish_angle = vectoangles(wish_angle); // And make a angle
\r
587 real_angle = wish_angle - self.angles;
\r
589 if (real_angle_x < 0) real_angle_x += 360;
\r
590 if (real_angle_x > 180) real_angle_x -= 360;
\r
592 if (real_angle_y < 0) real_angle_y += 360;
\r
593 if (real_angle_y > 180) real_angle_y -= 360;
\r
595 turn_limit = cvar("g_turrets_unit_walker_run_turnrate");
\r
596 // Convert from dgr/sec to dgr/tic
\r
597 turn_limit = turn_limit / (1 / self.ticrate);
\r
599 //real_angle_x = bound((-1 * turn_limit),real_angle_x, turn_limit);
\r
600 real_angle_y = bound((-1 * turn_limit),real_angle_y, turn_limit);
\r
602 self.angles_y = self.angles_y + real_angle_y;
\r
606 v_forward = normalize(self.enemy.origin - self.origin);
\r
608 v_forward = normalize(self.goalcurrent.origin - self.origin);
\r
610 makevectors(self.angles);
\r
612 if(self.flags & FL_ONGROUND)
\r
614 if(s_speed > s_run)
\r
615 self.velocity = (v_forward * max((s_speed - s_decel),s_run));
\r
616 if(s_speed <= s_run)
\r
617 self.velocity = (v_forward * min((s_speed + s_accel2),s_run));
\r
621 if(self.flags & FL_ONGROUND)
\r
623 makevectors(self.angles);
\r
625 self.velocity = min(s_speed - s_decel,0) * v_forward;
\r
636 void walker_attack()
\r
640 //turret_do_updates(self);
\r
642 self.tur_head.frame = self.tur_head.frame + 1;
\r
644 sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", 1, ATTN_NORM);
\r
647 fireBullet (self.tur_shotorg_updated, self.tur_shotdir_updated,self.shot_spread, self.shot_dmg, self.shot_force, DEATH_TURRET, FALSE);
\r
649 te_smallflash(self.tur_shotorg_updated);
\r
651 if(!(self.uzi_bulletcounter & 3))
\r
654 trailparticles(self,particleeffectnum("EF_MGTURRETTRAIL"),self.tur_shotorg_updated,trace_endpos);
\r
655 // te_lightning1(self,self.tur_shotorg_updated,trace_endpos);
\r
657 setmodel(flash, "models/uziflash.md3"); // precision set below
\r
658 setattachment(flash, self.tur_head, "tag_fire");
\r
660 flash.think = W_Uzi_Flash_Go;
\r
661 flash.nextthink = time + 0.02;
\r
663 flash.angles_z = flash.v_angle_z + random() * 180;
\r
665 flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
\r
668 self.uzi_bulletcounter = self.uzi_bulletcounter + 1;
\r
671 void walker_respawnhook()
\r
674 self.origin = self.wkr_spawn.origin;
\r
675 self.wkr_props.solid = SOLID_BBOX;
\r
676 self.wkr_props.alpha = 1;
\r
678 self.angles = self.wkr_spawn.angles;
\r
679 vtmp = self.origin;
\r
680 vtmp_z +=self.wkr_spawn.origin_z + self.wkr_spawn.maxs_z;
\r
681 setorigin(self,vtmp);
\r
684 void walker_diehook()
\r
686 self.wkr_props.solid = SOLID_NOT;
\r
687 self.wkr_props.alpha = -1;
\r
690 //.string target_start;
\r
691 void turret_walker_dinit()
\r
695 if (self.netname == "") self.netname = "Walker Turret";
\r
697 if(self.target != "")
\r
699 e = find(world,targetname,self.target);
\r
702 bprint("Warning! initital waypoint for Walker does NOT exsist!\n");
\r
709 if(e.classname != "walker_checkpoint")
\r
710 dprint("Warning: not a walker path\n");
\r
712 self.goalcurrent = e;
\r
718 self.wkr_props = spawn();
\r
719 self.wkr_spawn = spawn();
\r
721 self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
\r
722 self.turrcaps_flags = TFL_TURRCAPS_HITSCAN | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_ROAM | TFL_TURRCAPS_LINKED;
\r
723 self.aim_flags = TFL_AIM_LEAD | TFL_AIM_ZEASE;
\r
725 self.turret_respawnhook = walker_respawnhook;
\r
726 self.turret_diehook = walker_diehook;
\r
728 self.ticrate = 0.05;
\r
729 if (turret_stdproc_init("walker_std") == 0)
\r
734 // self.scale = 1.5;
\r
735 //setsize(self,'38 38 55','-38 -38 1');
\r
737 self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
\r
738 self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
\r
740 //self.flags = FL_CLIENT;
\r
741 self.iscreature = TRUE;
\r
742 self.movetype = MOVETYPE_WALK;
\r
743 self.solid = SOLID_BBOX;// SOLID_SLIDEBOX;
\r
744 self.takedamage = DAMAGE_AIM;
\r
746 setmodel(self.wkr_props,"models/turrets/walker_props.md3");
\r
747 setmodel(self.wkr_spawn,"models/turrets/walker_spawn.md3");
\r
748 setorigin(self.wkr_spawn,self.origin);
\r
750 self.wkr_spawn.angles = self.angles;
\r
751 self.wkr_spawn.solid = SOLID_NOT;
\r
753 traceline(self.wkr_spawn.origin + '0 0 10', self.wkr_spawn.origin - '0 0 10000', MOVE_NOMONSTERS, self);
\r
754 setorigin(self.wkr_spawn,trace_endpos + '0 0 4');
\r
756 setmodel(self,"models/turrets/walker_body.md3");
\r
757 setmodel(self.tur_head,"models/turrets/walker_head_minigun.md3");
\r
759 setattachment(self.tur_head,self,"tag_head");
\r
760 setattachment(self.wkr_props,self,"tag_head");
\r
764 f = gettagindex(self.tur_head,"tag_fire");
\r
765 v = gettaginfo(self.tur_head,f);
\r
768 setsize(self,WALKER_MIN,WALKER_MAX);
\r
769 //setsize(self,'-70 -70 0','70 70 55');
\r
771 self.tur_shotorg = v;
\r
772 self.tur_aimorg = v;
\r
774 self.idle_aim = '0 0 0';
\r
776 // self.v_home = self.origin;
\r
778 self.turret_firecheckfunc = walker_firecheck;
\r
780 // Our fire routine
\r
781 self.turret_firefunc = walker_attack;
\r
783 self.turret_postthink = walker_postthink;
\r
788 void spawnfunc_turret_walker()
\r
790 precache_model ("models/turrets/walker_head_minigun.md3");
\r
791 precache_model ("models/turrets/walker_body.md3");
\r
792 precache_model ("models/turrets/walker_props.md3");
\r
793 precache_model ("models/turrets/walker_spawn.md3");
\r
794 precache_model ( "models/turrets/rocket.md3");
\r
796 self.think = turret_walker_dinit;
\r
797 self.nextthink = time + 0.5;
\r