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
80 if (self.frame > 25)
\r
85 self.frame = self.frame + 2;
\r
86 if (self.frame > 25)
\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
136 void walker_rocket_explode()
\r
140 if(self.event_damage != SUB_Null)
\r
142 self.event_damage = SUB_Null;
\r
143 self.think = walker_rocket_explode;
\r
144 self.nextthink = time;
\r
148 sound (self, CHAN_PROJECTILE, "weapons/rocket_impact.wav", 1, ATTN_NORM);
\r
149 org2 = findbetterlocation (self.origin, 16);
\r
151 WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
\r
152 WriteByte (MSG_BROADCAST, 78);
\r
153 WriteCoord (MSG_BROADCAST, org2_x);
\r
154 WriteCoord (MSG_BROADCAST, org2_y);
\r
155 WriteCoord (MSG_BROADCAST, org2_z);
\r
157 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
162 void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
\r
164 self.health = self.health - damage;
\r
165 self.velocity = self.velocity + vforce;
\r
166 if (self.health <= 0) walker_rocket_explode();
\r
171 g_turrets_unit_walker_std_rocket_refire
\r
172 g_turrets_unit_walker_std_rocket_dmg
\r
173 g_turrets_unit_walker_std_rocket_radius
\r
174 g_turrets_unit_walker_std_rocket_force
\r
175 g_turrets_unit_walker_std_rocket_tunrate
\r
176 g_turrets_unit_walker_std_rocket_speed
\r
177 g_turrets_unit_walker_std_rocket_speed_add
\r
180 void walker_rocket_loop();
\r
181 void walker_rocket_think()
\r
183 vector olddir,newdir;
\r
188 self.nextthink = time + 0.1;
\r
190 olddir = normalize(self.velocity);
\r
191 edist = vlen(self.enemy.origin - self.origin);
\r
193 // Simulate crude guidance
\r
194 if (self.cnt < time)
\r
197 self.tur_shotorg = randomvec() * min(edist,64);
\r
199 self.tur_shotorg = randomvec() * min(edist,256);
\r
200 self.cnt = time + 0.5;
\r
203 self.tur_shotorg = '0 0 0';
\r
206 if (self.tur_health < time)
\r
208 self.think = walker_rocket_explode;
\r
209 self.nextthink = time;
\r
213 if ((random() < 0.01) && (self.shot_dmg != 1337))
\r
215 walker_rocket_loop();
\r
219 olddir = normalize(self.velocity);
\r
222 m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
\r
224 // Enemy dead? just keep on the current heading then.
\r
225 if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
\r
228 // Make sure we dont return to tracking a respawned player
\r
229 self.enemy = world;
\r
232 self.angles = vectoangles(self.velocity);
\r
237 // Predict enemy position
\r
238 itime = max(edist / m_speed,1);
\r
239 newdir = normalize((self.enemy.origin + self.tur_shotorg) - self.origin);
\r
243 //pre_pos = self.origin + olddir;
\r
248 newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate"));
\r
250 self.velocity = newdir * m_speed;
\r
253 self.angles = vectoangles(self.velocity);
\r
255 if (time+itime < time+0.1)
\r
257 self.think = turret_hellion_missile_explode;
\r
258 self.nextthink = time + itime;
\r
262 void walker_rocket_loop3()
\r
264 self.nextthink = time + 0.1;
\r
266 if (vlen(self.origin - self.tur_shotorg) < 128 )
\r
268 self.think = walker_rocket_think;
\r
276 m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
\r
277 olddir = normalize(self.velocity);
\r
278 newdir = normalize(self.tur_shotorg - self.origin);
\r
279 newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate"));
\r
281 self.velocity = newdir * m_speed;
\r
282 self.angles = vectoangles(self.velocity);
\r
285 void walker_rocket_loop2()
\r
287 self.nextthink = time + 0;
\r
289 if (vlen(self.origin - self.tur_shotorg) < 128 )
\r
291 self.tur_shotorg = self.origin - '0 0 200';
\r
292 self.think = walker_rocket_loop3;
\r
300 m_speed = vlen(self.velocity) + cvar("g_turrets_unit_walker_std_rocket_speed_add");
\r
301 olddir = normalize(self.velocity);
\r
302 newdir = normalize(self.tur_shotorg - self.origin);
\r
303 newdir = normalize(olddir + newdir * cvar("g_turrets_unit_walker_std_rocket_tunrate"));
\r
304 self.velocity = newdir * m_speed;
\r
305 self.angles = vectoangles(self.velocity);
\r
309 void walker_rocket_loop()
\r
312 self.nextthink= time + 0;
\r
313 self.tur_shotorg = self.origin + '0 0 400';
\r
314 self.think = walker_rocket_loop2;
\r
315 self.shot_dmg = 1337;
\r
318 void walker_fire_rocket(vector org)
\r
324 //self.angles_x *= -1;
\r
325 makevectors(self.angles);
\r
326 //self.angles_x *= -1;
\r
329 setorigin(rocket, org);
\r
331 sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", 1, ATTN_NORM);
\r
332 sound (rocket, CHAN_PROJECTILE, "weapons/rocket_fly.wav", 0.4, ATTN_NORM);
\r
333 setmodel (rocket, "models/turrets/rocket.md3"); // precision set below
\r
334 setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
\r
336 rocket.classname = "walker_rocket";
\r
337 rocket.owner = self;
\r
338 rocket.bot_dodge = TRUE;
\r
339 rocket.bot_dodgerating = 50;
\r
340 rocket.takedamage = DAMAGE_YES;
\r
342 rocket.damageforcescale = 2;
\r
343 rocket.health = 10;
\r
344 rocket.tur_shotorg = randomvec() * 512;
\r
345 rocket.cnt = time + 1;
\r
346 rocket.enemy = self.enemy;
\r
348 if (random() < 0.01)
\r
349 rocket.think = walker_rocket_loop;
\r
351 rocket.think = walker_rocket_think;
\r
353 rocket.event_damage = walker_rocket_damage;
\r
355 rocket.nextthink = time + 0.2;
\r
356 rocket.solid = SOLID_BBOX;
\r
357 rocket.movetype = MOVETYPE_FLYMISSILE;
\r
358 rocket.effects = EF_LOWPRECISION;
\r
359 rocket.velocity = ((v_forward + v_up * 0.35) +(randomvec() * 0.15))* cvar("g_turrets_unit_walker_std_rocket_speed");
\r
360 rocket.angles = vectoangles(rocket.velocity);
\r
361 rocket.touch = walker_rocket_explode;
\r
362 rocket.flags = FL_PROJECTILE;
\r
363 rocket.solid = SOLID_BBOX;
\r
364 rocket.tur_health = time + 9;
\r
366 te_explosion (rocket.origin);
\r
374 #define s_accel2 16
\r
382 self.cnt = self.cnt -1;
\r
391 f = gettagindex(self.owner,"tag_rocket01");
\r
393 f = gettagindex(self.owner,"tag_rocket02");
\r
395 org = self.owner.origin + gettaginfo(self.owner,f);
\r
398 self.nextthink = time + 0.2;
\r
400 walker_fire_rocket(org);
\r
403 void walker_postthink()
\r
409 if ((self.flags & FL_ONGROUND)&&(self.animflag != ANIM_MEELE))
\r
410 self.animflag = ANIM_NO;
\r
413 if (self.tur_head.attack_finished_single < time)
\r
417 rv.think = rv_think;
\r
418 rv.nextthink = time;
\r
422 self.tur_head.attack_finished_single = time + cvar("g_turrets_unit_walker_std_rocket_refire");
\r
426 if (self.checkpoint_path)
\r
428 if (vlen(self.origin - self.goalcurrent.origin) < 64)
\r
429 if (self.goalcurrent.path_next == world)
\r
432 self.checkpoint_path = world; // Path endpoint reached, go roaming.
\r
435 self.goalcurrent = self.goalcurrent.path_next;
\r
437 self.animflag = ANIM_WALK;
\r
439 else // Roaming mode
\r
444 wish_angle = angleofs(self,self.enemy); //normalize(self.origin-self.enemy.origin);
\r
446 if (self.tur_dist_enemy < cvar("g_turrets_unit_walker_std_meele_range"))
\r
449 if (fabs(wish_angle_y) < 15)
\r
450 self.animflag = ANIM_MEELE;
\r
454 if (fabs(wish_angle_y) < 15)
\r
455 self.animflag = ANIM_RUN;
\r
456 else if (fabs(wish_angle_y) < 30)
\r
457 self.animflag = ANIM_WALK;
\r
459 self.animflag = ANIM_TURN;
\r
464 if(self.animflag != ANIM_MEELE)
\r
465 self.animflag = ANIM_NO;
\r
471 s_speed = vlen(self.velocity);
\r
473 // Turn on the spot
\r
474 if (self.animflag == ANIM_TURN)
\r
477 wish_angle = normalize(self.enemy.origin - self.origin);
\r
479 wish_angle = normalize(self.goalcurrent.origin - self.origin);
\r
481 wish_angle = vectoangles(wish_angle);
\r
483 real_angle = wish_angle - self.angles;
\r
485 if (real_angle_x < 0) real_angle_x += 360;
\r
486 if (real_angle_x > 180) real_angle_x -= 360;
\r
488 if (real_angle_y < 0) real_angle_y += 360;
\r
489 if (real_angle_y > 180) real_angle_y -= 360;
\r
491 turn_limit = cvar("g_turrets_unit_walker_turn_turnrate");
\r
492 // Convert from dgr/sec to dgr/tic
\r
493 turn_limit = turn_limit / (1 / self.ticrate);
\r
495 //real_angle_x = bound((-1 * turn_limit),real_angle_x, turn_limit);
\r
496 real_angle_y = bound((-1 * turn_limit),real_angle_y, turn_limit);
\r
498 self.angles_y = self.angles_y + real_angle_y;
\r
501 v_forward = normalize(self.enemy.origin - self.origin);
\r
503 v_forward = normalize(self.goalcurrent.origin - self.origin);
\r
505 makevectors(self.angles);
\r
507 if (s_speed > s_turn)
\r
508 self.velocity = (v_forward * max((s_speed - s_decel),s_turn));
\r
509 if (s_speed < s_turn)
\r
510 self.velocity = (v_forward * min((s_speed + s_accel1),s_turn));
\r
512 else if (self.animflag == ANIM_WALK) // Gg walking
\r
514 if (self.goalcurrent)
\r
515 wish_angle = normalize(self.goalcurrent.origin - self.origin);
\r
518 wish_angle = normalize(self.enemy.origin - self.origin);
\r
520 wish_angle = self.angles;
\r
523 wish_angle = vectoangles(wish_angle); // And make a angle
\r
524 real_angle = wish_angle - self.angles;
\r
526 if (real_angle_x < 0) real_angle_x += 360;
\r
527 if (real_angle_x > 180) real_angle_x -= 360;
\r
529 if (real_angle_y < 0) real_angle_y += 360;
\r
530 if (real_angle_y > 180) real_angle_y -= 360;
\r
532 turn_limit = cvar("g_turrets_unit_walker_walk_turnrate");
\r
533 // Convert from dgr/sec to dgr/tic
\r
534 turn_limit = turn_limit / (1 / self.ticrate);
\r
536 //real_angle_x = bound((-1 * turn_limit),real_angle_x, turn_limit);
\r
537 real_angle_y = bound((-1 * turn_limit),real_angle_y, turn_limit);
\r
539 self.angles_y = self.angles_y + real_angle_y;
\r
541 if (self.goalcurrent)
\r
542 v_forward = normalize(self.goalcurrent.origin - self.origin);
\r
545 v_forward = normalize(self.enemy.origin - self.origin);
\r
547 makevectors(self.angles);
\r
548 self.velocity = v_forward * s_walk;
\r
550 //if(self.flags & FL_ONGROUND)
\r
554 s_z = self.velocity_z;
\r
555 if(s_speed > s_walk)
\r
556 self.velocity = (v_forward * max((s_speed - s_decel),s_walk));
\r
557 if(s_speed <= s_walk)
\r
558 self.velocity = (v_forward * min((s_speed + s_accel1),s_walk));
\r
559 self.velocity_z = s_z;//s_walk;
\r
565 else if (self.animflag == ANIM_RUN) // Move fast, turn slow
\r
567 if (self.goalcurrent)
\r
568 wish_angle = normalize(self.goalcurrent.origin - self.origin);
\r
571 wish_angle = normalize(self.enemy.origin - self.origin);
\r
573 wish_angle = self.angles;
\r
575 wish_angle = vectoangles(wish_angle); // And make a angle
\r
576 real_angle = wish_angle - self.angles;
\r
578 if (real_angle_x < 0) real_angle_x += 360;
\r
579 if (real_angle_x > 180) real_angle_x -= 360;
\r
581 if (real_angle_y < 0) real_angle_y += 360;
\r
582 if (real_angle_y > 180) real_angle_y -= 360;
\r
584 turn_limit = cvar("g_turrets_unit_walker_run_turnrate");
\r
585 // Convert from dgr/sec to dgr/tic
\r
586 turn_limit = turn_limit / (1 / self.ticrate);
\r
588 //real_angle_x = bound((-1 * turn_limit),real_angle_x, turn_limit);
\r
589 real_angle_y = bound((-1 * turn_limit),real_angle_y, turn_limit);
\r
591 self.angles_y = self.angles_y + real_angle_y;
\r
595 v_forward = normalize(self.enemy.origin - self.origin);
\r
597 v_forward = normalize(self.goalcurrent.origin - self.origin);
\r
599 makevectors(self.angles);
\r
601 if (self.flags & FL_ONGROUND)
\r
603 if (s_speed > s_run)
\r
604 self.velocity = (v_forward * max((s_speed - s_decel),s_run));
\r
605 if (s_speed <= s_run)
\r
606 self.velocity = (v_forward * min((s_speed + s_accel2),s_run));
\r
612 if (self.flags & FL_ONGROUND)
\r
614 makevectors(self.angles);
\r
616 self.velocity = min(s_speed - s_decel,0) * v_forward;
\r
627 void walker_attack()
\r
631 //turret_do_updates(self);
\r
633 self.tur_head.frame = self.tur_head.frame + 1;
\r
635 sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", 1, ATTN_NORM);
\r
638 fireBullet (self.tur_shotorg_updated, self.tur_shotdir_updated,self.shot_spread, self.shot_dmg, self.shot_force, DEATH_TURRET, FALSE);
\r
640 te_smallflash(self.tur_shotorg_updated);
\r
642 if (!(self.uzi_bulletcounter & 3))
\r
645 trailparticles(self,particleeffectnum("EF_MGTURRETTRAIL"),self.tur_shotorg_updated,trace_endpos);
\r
646 // te_lightning1(self,self.tur_shotorg_updated,trace_endpos);
\r
648 setmodel(flash, "models/uziflash.md3"); // precision set below
\r
649 setattachment(flash, self.tur_head, "tag_fire");
\r
651 flash.think = W_Uzi_Flash_Go;
\r
652 flash.nextthink = time + 0.02;
\r
654 flash.angles_z = flash.v_angle_z + random() * 180;
\r
656 flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
\r
659 self.uzi_bulletcounter = self.uzi_bulletcounter + 1;
\r
662 void walker_respawnhook()
\r
667 self.origin = self.wkr_spawn.origin;
\r
668 self.wkr_props.solid = SOLID_BBOX;
\r
669 self.wkr_props.alpha = 1;
\r
671 self.angles = self.wkr_spawn.angles;
\r
672 vtmp = self.origin;
\r
673 vtmp_z +=self.wkr_spawn.origin_z + self.wkr_spawn.maxs_z;
\r
674 setorigin(self,vtmp);
\r
676 if (self.target != "")
\r
678 e = find(world,targetname,self.target);
\r
681 bprint("Warning! initital waypoint for Walker does NOT exsist!\n");
\r
688 if (e.classname != "turret_checkpoint")
\r
689 dprint("Warning: not a turrret path\n");
\r
691 self.goalcurrent = e;
\r
694 void walker_diehook()
\r
697 self.wkr_props.solid = SOLID_NOT;
\r
698 self.wkr_props.alpha = -1;
\r
701 //.string target_start;
\r
702 void turret_walker_dinit()
\r
706 if (self.netname == "") self.netname = "Walker Turret";
\r
709 if (self.target != "")
\r
711 e = find(world,targetname,self.target);
\r
714 bprint("Warning! initital waypoint for Walker does NOT exsist!\n");
\r
718 if (e.classname != "turret_checkpoint")
\r
719 dprint("Warning: not a turrret path\n");
\r
721 self.goalcurrent = e;
\r
725 self.wkr_props = spawn();
\r
726 self.wkr_spawn = spawn();
\r
728 self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
\r
729 self.turrcaps_flags = TFL_TURRCAPS_HITSCAN | TFL_TURRCAPS_PLAYERKILL | TFL_TURRCAPS_MOVE | TFL_TURRCAPS_ROAM | TFL_TURRCAPS_LINKED;
\r
730 self.aim_flags = TFL_AIM_LEAD | TFL_AIM_ZEASE;
\r
732 self.turret_respawnhook = walker_respawnhook;
\r
733 self.turret_diehook = walker_diehook;
\r
735 self.ticrate = 0.05;
\r
736 if (turret_stdproc_init("walker_std") == 0)
\r
741 self.damage_flags |= RFL_DMG_DEATH_NOGIBS;
\r
743 self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
\r
744 self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;// | TFL_TARGETSELECT_LOS;
\r
746 //self.flags = FL_CLIENT;
\r
747 self.iscreature = TRUE;
\r
748 self.movetype = MOVETYPE_WALK;
\r
749 self.solid = SOLID_SLIDEBOX;
\r
750 self.takedamage = DAMAGE_AIM;
\r
752 setmodel(self.wkr_props,"models/turrets/walker_props.md3");
\r
753 setmodel(self.wkr_spawn,"models/turrets/walker_spawn.md3");
\r
754 setorigin(self.wkr_spawn,self.origin);
\r
756 self.wkr_spawn.angles = self.angles;
\r
757 self.wkr_spawn.solid = SOLID_NOT;
\r
759 traceline(self.wkr_spawn.origin + '0 0 10', self.wkr_spawn.origin - '0 0 10000', MOVE_NOMONSTERS, self);
\r
760 setorigin(self.wkr_spawn,trace_endpos + '0 0 4');
\r
762 setmodel(self,"models/turrets/walker_body.md3");
\r
763 setmodel(self.tur_head,"models/turrets/walker_head_minigun.md3");
\r
765 setattachment(self.tur_head,self,"tag_head");
\r
766 setattachment(self.wkr_props,self,"tag_head");
\r
770 f = gettagindex(self.tur_head,"tag_fire");
\r
771 v = gettaginfo(self.tur_head,f);
\r
774 setsize(self,WALKER_MIN,WALKER_MAX);
\r
775 //setsize(self,'-70 -70 0','70 70 55');
\r
777 self.tur_shotorg = v;
\r
778 self.tur_aimorg = v;
\r
780 self.idle_aim = '0 0 0';
\r
782 // self.v_home = self.origin;
\r
784 self.turret_firecheckfunc = walker_firecheck;
\r
786 // Our fire routine
\r
787 self.turret_firefunc = walker_attack;
\r
789 self.turret_postthink = walker_postthink;
\r
794 void spawnfunc_turret_walker()
\r
796 precache_model ("models/turrets/walker_head_minigun.md3");
\r
797 precache_model ("models/turrets/walker_body.md3");
\r
798 precache_model ("models/turrets/walker_props.md3");
\r
799 precache_model ("models/turrets/walker_spawn.md3");
\r
800 precache_model ( "models/turrets/rocket.md3");
\r
802 self.think = turret_walker_dinit;
\r
803 self.nextthink = time + 0.5;
\r