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;
73 self.frame = zombie_anim_deathback1;
75 self.frame = zombie_anim_deathfront1;
77 monster_hook_death(); // for post-death mods
80 void zombie_attack_standing()
82 float rand = random(), dot = 0, bigdmg = 0;
87 if(self.monster_owner == self.enemy)
93 bigdmg = autocvar_g_monster_zombie_attack_stand_damage * self.scale;
95 //print("zombie attacks!\n");
96 makevectors (self.angles);
97 dot = normalize (self.enemy.origin - self.origin) * v_forward;
100 Damage(self.enemy, self, self, bigdmg * monster_skill, DEATH_MONSTER_ZOMBIE_MELEE, self.origin, '0 0 0');
103 if(self.enemy.health < 1)
107 self.frame = zombie_anim_attackstanding1;
108 else if (rand < 0.66)
109 self.frame = zombie_anim_attackstanding2;
111 self.frame = zombie_anim_attackstanding3;
113 self.nextthink = time + autocvar_g_monster_zombie_attack_stand_delay;
114 self.attack_finished_single = self.nextthink;
117 void zombie_attack_leap_touch()
120 float bigdmg = autocvar_g_monster_zombie_attack_leap_damage * self.scale;
122 if (other.deadflag != DEAD_NO)
125 if (self.monster_owner == other)
128 if (other.takedamage == DAMAGE_NO)
131 //void Damage (entity targ, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
132 traceline(self.origin, other.origin, FALSE, self);
134 angles_face = vectoangles(self.moveto - self.origin);
135 angles_face = normalize(angles_face) * autocvar_g_monster_zombie_attack_leap_force;
136 Damage(other, self, self, bigdmg * monster_skill, DEATH_MONSTER_ZOMBIE_JUMP, trace_endpos, angles_face);
138 self.touch = MonsterTouch;
141 float zombie_attack_ranged()
143 makevectors(self.angles);
144 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))
152 self.think = zombie_think;
153 self.nextthink = time + 0.1;
155 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);
161 self.health = autocvar_g_monster_zombie_health * self.scale;
163 self.classname = "monster_zombie";
164 self.nextthink = time + 2.1;
165 self.frame = zombie_anim_spawn;
166 self.think = zombie_think;
167 self.sprite_height = 50 * self.scale;
168 self.checkattack = GenericCheckAttack;
169 self.attack_melee = zombie_attack_standing;
170 self.attack_ranged = zombie_attack_ranged;
171 self.skin = rint(random() * 4);
174 if(self.msound_idle == "") self.msound_idle = "monsters/zombie_idle.wav";
175 if(self.msound_death == "") self.msound_death = "monsters/zombie_death.wav";
176 if(self.msound_pain == "") self.msound_pain = "monsters/zombie_pain.wav";
177 if(self.msound_attack_melee == "") self.msound_attack_melee = "monsters/zombie_melee.wav";
178 if(self.msound_attack_ranged == "") self.msound_attack_ranged = "monsters/zombie_attack.wav";
179 if(self.msound_sight == "") self.msound_sight = "monsters/zombie_sight.wav";
181 monster_hook_spawn(); // for post-spawn mods
184 /*QUAKED monster_zombie (1 0 0) (-18 -18 -25) (18 18 47)
185 Zombie, 60 health points.
186 -------- KEYS --------
187 -------- SPAWNFLAGS --------
188 MONSTERFLAG_APPEAR: monster will spawn when triggered.
189 ---------NOTES----------
190 Original Quake 1 zombie entity used a smaller box ('-16 -16 -24', '16 16 32').
191 -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
192 modeldisabled="models/monsters/zombie.dpm"
194 void spawnfunc_monster_zombie()
196 if not(autocvar_g_monster_zombie) { remove(self); return; }
198 self.monster_spawnfunc = spawnfunc_monster_zombie;
200 if(self.spawnflags & MONSTERFLAG_APPEAR)
202 self.think = func_null;
204 self.use = Monster_Appear;
208 if not (monster_initialize(
210 "models/monsters/zombie.dpm",
211 ZOMBIE_MIN, ZOMBIE_MAX,
213 zombie_die, zombie_spawn))