]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/monsters/monster/zombie.qc
Remove unused neutral check from target validation & remove unnecessary enemy checks...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / monsters / monster / zombie.qc
1 /**
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
5  */
6  
7 // cvars
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;
19
20 // zombie animations
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
52
53 const vector ZOMBIE_MIN                          = '-18 -18 -25';
54 const vector ZOMBIE_MAX                          = '18 18 47';
55
56 void zombie_spawn();
57 void spawnfunc_monster_zombie();
58 void zombie_think();
59
60 void zombie_die ()
61 {
62         Monster_CheckDropCvars ("zombie");
63         
64         self.solid                      = SOLID_NOT;
65         self.takedamage         = DAMAGE_NO;
66         self.event_damage   = func_null;
67         self.enemy                      = world;
68         self.movetype           = MOVETYPE_TOSS;
69         self.think                      = Monster_Fade;
70         self.nextthink          = time + 2.1;
71         
72         if (random() > 0.5)
73                 self.frame = zombie_anim_deathback1;
74         else
75                 self.frame = zombie_anim_deathfront1;
76                 
77         monster_hook_death(); // for post-death mods
78 }
79
80 void zombie_attack_standing()
81 {
82         float rand = random(), dot = 0, bigdmg = 0;
83
84         self.velocity_x = 0;
85         self.velocity_y = 0;
86         
87         if(self.monster_owner == self.enemy)
88         {
89                 self.enemy = world;
90                 return;
91         }
92         
93         bigdmg = autocvar_g_monster_zombie_attack_stand_damage * self.scale;
94
95         //print("zombie attacks!\n");
96         makevectors (self.angles);
97         dot = normalize (self.enemy.origin - self.origin) * v_forward;
98         if(dot > 0.3)
99         {
100                 Damage(self.enemy, self, self, bigdmg * monster_skill, DEATH_MONSTER_ZOMBIE_MELEE, self.origin, '0 0 0');
101         }
102         
103         if(self.enemy.health < 1)
104                 self.enemy = world;
105                 
106         if (rand < 0.33)
107                 self.frame = zombie_anim_attackstanding1;
108         else if (rand < 0.66)
109                 self.frame = zombie_anim_attackstanding2;
110         else
111                 self.frame = zombie_anim_attackstanding3;
112
113         self.nextthink = time + autocvar_g_monster_zombie_attack_stand_delay;
114         self.attack_finished_single = self.nextthink;
115 }
116
117 void zombie_attack_leap_touch()
118 {
119         vector angles_face;
120         float bigdmg = autocvar_g_monster_zombie_attack_leap_damage * self.scale;
121         
122         if (other.deadflag != DEAD_NO)
123                 return;
124                 
125         if (self.monster_owner == other)
126                 return;
127         
128         if (other.takedamage == DAMAGE_NO)
129                 return;
130                 
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);
133
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);        
137                 
138         self.touch = MonsterTouch;
139 }
140
141 float zombie_attack_ranged()
142 {
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))
145                 return TRUE;
146                 
147         return FALSE;
148 }
149
150 void zombie_think()
151 {
152         self.think = zombie_think;
153         self.nextthink = time + 0.1;
154
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);
156 }
157
158 void zombie_spawn() 
159 {
160         if not(self.health)
161                 self.health = autocvar_g_monster_zombie_health * self.scale;
162         
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);
172         
173         // some sounds
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";
180         
181         monster_hook_spawn(); // for post-spawn mods
182 }
183
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"
193 */
194 void spawnfunc_monster_zombie() 
195 {
196         if not(autocvar_g_monster_zombie) { remove(self); return; }
197         
198         self.monster_spawnfunc = spawnfunc_monster_zombie;
199         
200         if(self.spawnflags & MONSTERFLAG_APPEAR)
201         {
202                 self.think = func_null;
203                 self.nextthink = -1;
204                 self.use = Monster_Appear;
205                 return;
206         }
207         
208         if not (monster_initialize(
209                          "Zombie",
210                          "models/monsters/zombie.dpm",
211                          ZOMBIE_MIN, ZOMBIE_MAX,
212                          FALSE,
213                          zombie_die, zombie_spawn))
214         {
215                 remove(self);
216                 return;
217         }
218 }