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