]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/monsters/monster/zombie.qc
Merge branch 'master' into Mario/turrets
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / monsters / monster / zombie.qc
1 #ifndef MENUQC
2 bool m_zombie(int);
3 #endif
4 REGISTER_MONSTER_SIMPLE(
5 /* MON_##id   */ ZOMBIE,
6 /* spawnflags */ MON_FLAG_MELEE,
7 /* mins,maxs  */ '-18 -18 -25', '18 18 47',
8 /* model      */ "zombie.dpm",
9 /* netname    */ "zombie",
10 /* fullname   */ _("Zombie")
11 ) {
12 #ifndef MENUQC
13         this.monster_func = m_zombie;
14 #endif
15 }
16
17 #ifdef SVQC
18 float autocvar_g_monster_zombie_health;
19 float autocvar_g_monster_zombie_attack_melee_damage;
20 float autocvar_g_monster_zombie_attack_melee_delay;
21 float autocvar_g_monster_zombie_attack_leap_damage;
22 float autocvar_g_monster_zombie_attack_leap_force;
23 float autocvar_g_monster_zombie_attack_leap_speed;
24 float autocvar_g_monster_zombie_attack_leap_delay;
25 float autocvar_g_monster_zombie_speed_stop;
26 float autocvar_g_monster_zombie_speed_run;
27 float autocvar_g_monster_zombie_speed_walk;
28
29 const float zombie_anim_attackleap                      = 0;
30 const float zombie_anim_attackrun1                      = 1;
31 const float zombie_anim_attackrun2                      = 2;
32 const float zombie_anim_attackrun3                      = 3;
33 const float zombie_anim_attackstanding1         = 4;
34 const float zombie_anim_attackstanding2         = 5;
35 const float zombie_anim_attackstanding3         = 6;
36 const float zombie_anim_blockend                        = 7;
37 const float zombie_anim_blockstart                      = 8;
38 const float zombie_anim_deathback1                      = 9;
39 const float zombie_anim_deathback2                      = 10;
40 const float zombie_anim_deathback3                      = 11;
41 const float zombie_anim_deathfront1                     = 12;
42 const float zombie_anim_deathfront2                     = 13;
43 const float zombie_anim_deathfront3                     = 14;
44 const float zombie_anim_deathleft1                      = 15;
45 const float zombie_anim_deathleft2                      = 16;
46 const float zombie_anim_deathright1                     = 17;
47 const float zombie_anim_deathright2                     = 18;
48 const float zombie_anim_idle                            = 19;
49 const float zombie_anim_painback1                       = 20;
50 const float zombie_anim_painback2                       = 21;
51 const float zombie_anim_painfront1                      = 22;
52 const float zombie_anim_painfront2                      = 23;
53 const float zombie_anim_runbackwards            = 24;
54 const float zombie_anim_runbackwardsleft        = 25;
55 const float zombie_anim_runbackwardsright       = 26;
56 const float zombie_anim_runforward                      = 27;
57 const float zombie_anim_runforwardleft          = 28;
58 const float zombie_anim_runforwardright         = 29;
59 const float zombie_anim_spawn                           = 30;
60
61 void zombie_attack_leap_touch()
62 {
63         if (self.health <= 0)
64                 return;
65
66         vector angles_face;
67
68         if(other.takedamage)
69         {
70                 angles_face = vectoangles(self.moveto - self.origin);
71                 angles_face = normalize(angles_face) * (autocvar_g_monster_zombie_attack_leap_force);
72                 Damage(other, self, self, (autocvar_g_monster_zombie_attack_leap_damage) * Monster_SkillModifier(), DEATH_MONSTER_ZOMBIE_JUMP, other.origin, angles_face);
73                 self.touch = MonsterTouch; // instantly turn it off to stop damage spam
74         }
75
76         if (trace_dphitcontents)
77                 self.touch = MonsterTouch;
78 }
79
80 void zombie_blockend()
81 {
82         if(self.health <= 0)
83                 return;
84
85         self.frame = zombie_anim_blockend;
86         self.armorvalue = 0;
87         self.m_armor_blockpercent = autocvar_g_monsters_armor_blockpercent;
88 }
89
90 float zombie_block()
91 {
92         self.frame = zombie_anim_blockstart;
93         self.armorvalue = 100;
94         self.m_armor_blockpercent = 0.9;
95         self.state = MONSTER_STATE_ATTACK_MELEE; // freeze monster
96         self.attack_finished_single = time + 2.1;
97
98         defer(2, zombie_blockend);
99
100         return true;
101 }
102
103 float zombie_attack(float attack_type)
104 {
105         switch(attack_type)
106         {
107                 case MONSTER_ATTACK_MELEE:
108                 {
109                         float rand = random(), chosen_anim;
110
111                         if(rand < 0.33)
112                                 chosen_anim = zombie_anim_attackstanding1;
113                         else if(rand < 0.66)
114                                 chosen_anim = zombie_anim_attackstanding2;
115                         else
116                                 chosen_anim = zombie_anim_attackstanding3;
117
118                         if(random() < 0.3 && self.health < 75 && self.enemy.health > 10)
119                                 return zombie_block();
120
121                         return monster_melee(self.enemy, (autocvar_g_monster_zombie_attack_melee_damage), chosen_anim, self.attack_range, (autocvar_g_monster_zombie_attack_melee_delay), DEATH_MONSTER_ZOMBIE_MELEE, true);
122                 }
123                 case MONSTER_ATTACK_RANGED:
124                 {
125                         makevectors(self.angles);
126                         return 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));
127                 }
128         }
129
130         return false;
131 }
132
133 void spawnfunc_monster_zombie()
134 {
135         self.classname = "monster_zombie";
136
137         if(!monster_initialize(MON_ZOMBIE.monsterid)) { remove(self); return; }
138 }
139
140 float m_zombie(float req)
141 {
142         switch(req)
143         {
144                 case MR_THINK:
145                 {
146                         monster_move((autocvar_g_monster_zombie_speed_run), (autocvar_g_monster_zombie_speed_walk), (autocvar_g_monster_zombie_speed_stop), zombie_anim_runforward, zombie_anim_runforward, zombie_anim_idle);
147                         return true;
148                 }
149                 case MR_DEATH:
150                 {
151                         self.armorvalue = 0;
152                         self.m_armor_blockpercent = autocvar_g_monsters_armor_blockpercent;
153                         self.frame = ((random() > 0.5) ? zombie_anim_deathback1 : zombie_anim_deathfront1);
154                         return true;
155                 }
156                 case MR_SETUP:
157                 {
158                         if(!self.health) self.health = (autocvar_g_monster_zombie_health);
159
160                         if(self.spawnflags & MONSTERFLAG_NORESPAWN)
161                                 self.spawnflags &= ~MONSTERFLAG_NORESPAWN; // zombies always respawn
162
163                         self.spawnflags |= MONSTER_RESPAWN_DEATHPOINT;
164
165                         self.monster_loot = spawnfunc_item_health_medium;
166                         self.monster_attackfunc = zombie_attack;
167                         self.frame = zombie_anim_spawn;
168                         self.spawn_time = time + 2.1;
169                         self.spawnshieldtime = self.spawn_time;
170                         self.respawntime = 0.2;
171
172                         return true;
173                 }
174                 case MR_PRECACHE:
175                 {
176                         precache_model("models/monsters/zombie.dpm");
177                         return true;
178                 }
179         }
180
181         return true;
182 }
183
184 #endif // SVQC
185 #ifdef CSQC
186 float m_zombie(float req)
187 {
188         switch(req)
189         {
190                 case MR_PRECACHE:
191                 {
192                         return true;
193                 }
194         }
195
196         return true;
197 }
198
199 #endif // CSQC