]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/monsters/monster/zombie.qc
Merge branch 'master' into Mario/monsters
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / monsters / monster / zombie.qc
1 #ifdef REGISTER_MONSTER
2 REGISTER_MONSTER(
3 /* MON_##id   */ ZOMBIE,
4 /* function   */ m_zombie,
5 /* spawnflags */ MON_FLAG_MELEE,
6 /* mins,maxs  */ '-18 -18 -25', '18 18 47',
7 /* model      */ "zombie.dpm",
8 /* netname    */ "zombie",
9 /* fullname   */ _("Zombie")
10 );
11
12 #define ZOMBIE_SETTINGS(monster) \
13         MON_ADD_CVAR(monster, health) \
14         MON_ADD_CVAR(monster, attack_melee_damage) \
15         MON_ADD_CVAR(monster, attack_melee_delay) \
16         MON_ADD_CVAR(monster, attack_leap_damage) \
17         MON_ADD_CVAR(monster, attack_leap_force) \
18         MON_ADD_CVAR(monster, attack_leap_speed) \
19         MON_ADD_CVAR(monster, attack_leap_delay) \
20         MON_ADD_CVAR(monster, speed_stop) \
21         MON_ADD_CVAR(monster, speed_run) \
22         MON_ADD_CVAR(monster, speed_walk) 
23
24 #ifdef SVQC
25 ZOMBIE_SETTINGS(zombie)
26 #endif // SVQC
27 #else
28 #ifdef SVQC
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) * MON_CVAR(zombie, attack_leap_force);
72                 Damage(other, self, self, MON_CVAR(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, MON_CVAR(zombie, attack_melee_damage), chosen_anim, self.attack_range, MON_CVAR(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 * MON_CVAR(zombie, attack_leap_speed) + '0 0 200', MON_CVAR(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         self.monster_spawnfunc = spawnfunc_monster_zombie;
138         
139         self.spawnflags |= MONSTER_RESPAWN_DEATHPOINT;
140         
141         if(Monster_CheckAppearFlags(self))
142                 return;
143         
144         if not(monster_initialize(MON_ZOMBIE, FALSE)) { remove(self); return; }
145 }
146
147 float m_zombie(float req)
148 {
149         switch(req)
150         {
151                 case MR_THINK:
152                 {
153                         monster_move(MON_CVAR(zombie, speed_run), MON_CVAR(zombie, speed_walk), MON_CVAR(zombie, speed_stop), zombie_anim_runforward, zombie_anim_runforward, zombie_anim_idle);
154                         return TRUE;
155                 }
156                 case MR_DEATH:
157                 {
158                         self.armorvalue = 0;
159                         self.m_armor_blockpercent = autocvar_g_monsters_armor_blockpercent;
160                         self.frame = ((random() > 0.5) ? zombie_anim_deathback1 : zombie_anim_deathfront1);
161                         return TRUE;
162                 }
163                 case MR_SETUP:
164                 {
165                         if not(self.health) self.health = MON_CVAR(zombie, health);
166                         
167                         if(self.spawnflags & MONSTERFLAG_NORESPAWN)
168                                 self.spawnflags &= ~MONSTERFLAG_NORESPAWN; // zombies always respawn
169                         
170                         self.monster_loot = spawnfunc_item_health_medium;
171                         self.monster_attackfunc = zombie_attack;
172                         self.frame = zombie_anim_spawn;
173                         self.spawn_time = time + 2.1;
174                         self.spawnshieldtime = self.spawn_time;
175                         self.respawntime = 0.2;
176                         
177                         return TRUE;
178                 }
179                 case MR_PRECACHE:
180                 {
181                         precache_model ("models/monsters/zombie.dpm");
182                         return TRUE;
183                 }
184                 case MR_CONFIG:
185                 {
186                         MON_CONFIG_SETTINGS(ZOMBIE_SETTINGS(zombie))
187                         return TRUE;
188                 }
189         }
190         
191         return TRUE;
192 }
193
194 #endif // SVQC
195 #ifdef CSQC
196 float m_zombie(float req)
197 {
198         switch(req)
199         {
200                 case MR_PRECACHE:
201                 {
202                         precache_model ("models/monsters/zombie.dpm");
203                         return TRUE;
204                 }
205         }
206         
207         return TRUE;
208 }
209
210 #endif // CSQC
211 #endif // REGISTER_MONSTER