]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/monsters/monster/zombie.qc
Fix monster color resetting when it respawns
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / monsters / monster / zombie.qc
1 // size
2 const vector ZOMBIE_MIN = '-18 -18 -25';
3 const vector ZOMBIE_MAX = '18 18 47';
4
5 // model
6 string ZOMBIE_MODEL = "models/monsters/zombie.dpm";
7
8 #ifdef SVQC
9 // cvars
10 float autocvar_g_monster_zombie;
11 float autocvar_g_monster_zombie_stopspeed;
12 float autocvar_g_monster_zombie_attack_leap_damage;
13 float autocvar_g_monster_zombie_attack_leap_delay;
14 float autocvar_g_monster_zombie_attack_leap_force;
15 float autocvar_g_monster_zombie_attack_leap_speed;
16 float autocvar_g_monster_zombie_attack_stand_damage;
17 float autocvar_g_monster_zombie_attack_stand_delay;
18 float autocvar_g_monster_zombie_health;
19 float autocvar_g_monster_zombie_speed_walk;
20 float autocvar_g_monster_zombie_speed_run;
21
22 // animations
23 const float zombie_anim_attackleap                      = 0;
24 const float zombie_anim_attackrun1                      = 1;
25 const float zombie_anim_attackrun2                      = 2;
26 const float zombie_anim_attackrun3                      = 3;
27 const float zombie_anim_attackstanding1         = 4;
28 const float zombie_anim_attackstanding2         = 5;
29 const float zombie_anim_attackstanding3         = 6;
30 const float zombie_anim_blockend                        = 7;
31 const float zombie_anim_blockstart                      = 8;
32 const float zombie_anim_deathback1                      = 9;
33 const float zombie_anim_deathback2                      = 10;
34 const float zombie_anim_deathback3                      = 11;
35 const float zombie_anim_deathfront1                     = 12;
36 const float zombie_anim_deathfront2                     = 13;
37 const float zombie_anim_deathfront3                     = 14;
38 const float zombie_anim_deathleft1                      = 15;
39 const float zombie_anim_deathleft2                      = 16;
40 const float zombie_anim_deathright1                     = 17;
41 const float zombie_anim_deathright2                     = 18;
42 const float zombie_anim_idle                            = 19;
43 const float zombie_anim_painback1                       = 20;
44 const float zombie_anim_painback2                       = 21;
45 const float zombie_anim_painfront1                      = 22;
46 const float zombie_anim_painfront2                      = 23;
47 const float zombie_anim_runbackwards            = 24;
48 const float zombie_anim_runbackwardsleft        = 25;
49 const float zombie_anim_runbackwardsright       = 26;
50 const float zombie_anim_runforward                      = 27;
51 const float zombie_anim_runforwardleft          = 28;
52 const float zombie_anim_runforwardright         = 29;
53 const float zombie_anim_spawn                           = 30;
54
55 void zombie_think()
56 {
57         self.think = zombie_think;
58         self.nextthink = time + self.ticrate;
59
60         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);
61 }
62
63 void zombie_attack_leap_touch ()
64 {
65         if (self.health <= 0)
66                 return;
67                 
68         vector angles_face;
69
70         if(other.takedamage)
71         {
72                 angles_face = vectoangles(self.moveto - self.origin);
73                 angles_face = normalize(angles_face) * autocvar_g_monster_zombie_attack_leap_force;
74                 Damage(other, self, self, autocvar_g_monster_zombie_attack_leap_damage * monster_skill, DEATH_MONSTER_ZOMBIE_JUMP, other.origin, angles_face);
75                 self.touch = MonsterTouch; // instantly turn it off to stop damage spam
76         }
77
78         if (trace_dphitcontents)
79                 self.touch = MonsterTouch;
80 }
81
82 float zombie_attack(float attack_type)
83 {
84         switch(attack_type)
85         {
86                 case MONSTER_ATTACK_MELEE:
87                 {
88                         float rand = random(), chosen_anim;
89                 
90                         if(rand < 0.33)
91                                 chosen_anim = zombie_anim_attackstanding1;
92                         else if(rand < 0.66)
93                                 chosen_anim = zombie_anim_attackstanding2;
94                         else
95                                 chosen_anim = zombie_anim_attackstanding3;
96                                 
97                         monsters_setframe(chosen_anim);
98
99                         self.attack_finished_single = time + autocvar_g_monster_zombie_attack_stand_delay;
100                         
101                         monster_melee(self.enemy, autocvar_g_monster_zombie_attack_stand_damage, 0.3, DEATH_MONSTER_ZOMBIE_MELEE, TRUE);
102                         
103                         return TRUE;
104                 }
105                 case MONSTER_ATTACK_RANGED:
106                 {
107                         makevectors(self.angles);
108                         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))
109                                 return TRUE;
110                 }
111         }
112         
113         return FALSE;
114 }
115
116 void zombie_die ()
117 {
118         Monster_CheckDropCvars ("zombie");
119         
120         self.think = monster_dead_think;
121         self.nextthink = time + self.ticrate;
122         self.ltime = time + 5;
123         monsters_setframe((random() > 0.5) ? zombie_anim_deathback1 : zombie_anim_deathfront1);
124                 
125         monster_hook_death(); // for post-death mods
126 }
127
128 void zombie_spawn() 
129 {
130         if not(self.health)
131                 self.health = autocvar_g_monster_zombie_health;
132         
133         self.classname                  = "monster_zombie";
134         self.spawn_time                 = time + 2.1;
135         self.nextthink                  = time + random() * 0.5 + 0.1;
136         self.think                              = zombie_think;
137         self.monster_attackfunc = zombie_attack;
138         self.respawntime                = 0.1;
139         self.spawnflags            |= MONSTER_RESPAWN_DEATHPOINT; // always enabled for zombie
140         
141         monsters_setframe(zombie_anim_spawn);
142         
143         monster_setupsounds("zombie");
144         
145         monster_hook_spawn(); // for post-spawn mods
146 }
147
148 void spawnfunc_monster_zombie() 
149 {
150         if not(autocvar_g_monster_zombie) { remove(self); return; }
151         
152         self.monster_spawnfunc = spawnfunc_monster_zombie;
153         
154         if(Monster_CheckAppearFlags(self))
155                 return;
156         
157         if not (monster_initialize(
158                          "Zombie", MONSTER_ZOMBIE,
159                          ZOMBIE_MIN, ZOMBIE_MAX,
160                          FALSE,
161                          zombie_die, zombie_spawn))
162         {
163                 remove(self);
164                 return;
165         }
166 }
167
168 #endif //SVQC