2 * Special purpose fields:
3 * .delay - time at which to check if zombie's enemy is still in range
4 * .enemy - enemy of this zombie
8 float autocvar_g_monster_zombie;
9 float autocvar_g_monster_zombie_stopspeed;
10 float autocvar_g_monster_zombie_attack_leap_damage;
11 float autocvar_g_monster_zombie_attack_leap_delay;
12 float autocvar_g_monster_zombie_attack_leap_force;
13 float autocvar_g_monster_zombie_attack_leap_speed;
14 float autocvar_g_monster_zombie_attack_stand_damage;
15 float autocvar_g_monster_zombie_attack_stand_delay;
16 float autocvar_g_monster_zombie_health;
17 float autocvar_g_monster_zombie_speed_walk;
18 float autocvar_g_monster_zombie_speed_run;
21 #define zombie_anim_attackleap 0
22 #define zombie_anim_attackrun1 1
23 #define zombie_anim_attackrun2 2
24 #define zombie_anim_attackrun3 3
25 #define zombie_anim_attackstanding1 4
26 #define zombie_anim_attackstanding2 5
27 #define zombie_anim_attackstanding3 6
28 #define zombie_anim_blockend 7
29 #define zombie_anim_blockstart 8
30 #define zombie_anim_deathback1 9
31 #define zombie_anim_deathback2 10
32 #define zombie_anim_deathback3 11
33 #define zombie_anim_deathfront1 12
34 #define zombie_anim_deathfront2 13
35 #define zombie_anim_deathfront3 14
36 #define zombie_anim_deathleft1 15
37 #define zombie_anim_deathleft2 16
38 #define zombie_anim_deathright1 17
39 #define zombie_anim_deathright2 18
40 #define zombie_anim_idle 19
41 #define zombie_anim_painback1 20
42 #define zombie_anim_painback2 21
43 #define zombie_anim_painfront1 22
44 #define zombie_anim_painfront2 23
45 #define zombie_anim_runbackwards 24
46 #define zombie_anim_runbackwardsleft 25
47 #define zombie_anim_runbackwardsright 26
48 #define zombie_anim_runforward 27
49 #define zombie_anim_runforwardleft 28
50 #define zombie_anim_runforwardright 29
51 #define zombie_anim_spawn 30
53 const vector ZOMBIE_MIN = '-18 -18 -25';
54 const vector ZOMBIE_MAX = '18 18 47';
57 void spawnfunc_monster_zombie();
62 Monster_CheckDropCvars ("zombie");
64 self.solid = SOLID_NOT;
65 self.takedamage = DAMAGE_NO;
66 self.event_damage = func_null;
68 self.movetype = MOVETYPE_TOSS;
69 self.think = Monster_Fade;
70 self.nextthink = time + 2.1;
71 self.pain_finished = self.nextthink;
74 self.frame = zombie_anim_deathback1;
76 self.frame = zombie_anim_deathfront1;
78 monster_hook_death(); // for post-death mods
81 void zombie_attack_standing()
83 float rand = random(), dot = 0, bigdmg = 0;
88 if(self.monster_owner == self.enemy)
94 bigdmg = autocvar_g_monster_zombie_attack_stand_damage * self.scale;
96 //print("zombie attacks!\n");
97 makevectors (self.angles);
98 dot = normalize (self.enemy.origin - self.origin) * v_forward;
101 Damage(self.enemy, self, self, bigdmg * monster_skill, DEATH_MONSTER_MELEE, self.origin, '0 0 0');
104 if(self.enemy.health < 1)
108 self.frame = zombie_anim_attackstanding1;
109 else if (rand < 0.66)
110 self.frame = zombie_anim_attackstanding2;
112 self.frame = zombie_anim_attackstanding3;
114 self.nextthink = time + autocvar_g_monster_zombie_attack_stand_delay;
115 self.attack_finished_single = self.nextthink;
118 void zombie_attack_leap_touch()
121 float bigdmg = autocvar_g_monster_zombie_attack_leap_damage * self.scale;
123 if (other.deadflag != DEAD_NO)
126 if (self.monster_owner == other)
129 if (other.takedamage == DAMAGE_NO)
132 //void Damage (entity targ, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
133 traceline(self.origin, other.origin, FALSE, self);
135 angles_face = vectoangles(self.moveto - self.origin);
136 angles_face = normalize(angles_face) * autocvar_g_monster_zombie_attack_leap_force;
137 Damage(other, self, self, bigdmg * monster_skill, DEATH_MONSTER_MELEE, trace_endpos, angles_face);
139 self.touch = MonsterTouch;
142 float zombie_attack_ranged()
144 makevectors(self.angles);
145 if(monster_leap(zombie_anim_attackleap, zombie_attack_leap_touch, v_forward * autocvar_g_monster_zombie_attack_leap_speed + '0 0 200', autocvar_g_monster_zombie_attack_leap_delay))
153 self.think = zombie_think;
154 self.nextthink = time + 0.1;
156 monster_move(autocvar_g_monster_zombie_speed_run, autocvar_g_monster_zombie_speed_walk, autocvar_g_monster_zombie_stopspeed, zombie_anim_runforward, zombie_anim_runforward, zombie_anim_idle);
162 self.health = autocvar_g_monster_zombie_health * self.scale;
164 self.classname = "monster_zombie";
165 self.nextthink = time + 2.1;
166 self.pain_finished = self.nextthink;
167 self.frame = zombie_anim_spawn;
168 self.think = zombie_think;
169 self.sprite_height = 50 * self.scale;
170 self.checkattack = GenericCheckAttack;
171 self.attack_melee = zombie_attack_standing;
172 self.attack_ranged = zombie_attack_ranged;
173 self.skin = rint(random() * 4);
175 monster_hook_spawn(); // for post-spawn mods
178 /*QUAKED monster_zombie (1 0 0) (-18 -18 -25) (18 18 47)
179 Zombie, 60 health points.
180 -------- KEYS --------
181 -------- SPAWNFLAGS --------
182 MONSTERFLAG_APPEAR: monster will spawn when triggered.
183 ---------NOTES----------
184 Original Quake 1 zombie entity used a smaller box ('-16 -16 -24', '16 16 32').
185 -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
186 modeldisabled="models/monsters/zombie.dpm"
188 void spawnfunc_monster_zombie()
190 if not(autocvar_g_monster_zombie)
196 self.monster_spawnfunc = spawnfunc_monster_zombie;
198 if(self.spawnflags & MONSTERFLAG_APPEAR)
200 self.think = func_null;
202 self.use = Monster_Appear;
206 if not (monster_initialize(
208 "models/monsters/zombie.dpm",
209 ZOMBIE_MIN, ZOMBIE_MAX,
211 zombie_die, zombie_spawn))