Xonotic
zombie.qc
Go to the documentation of this file.
1 #include "zombie.qh"
2 
3 #ifdef SVQC
4 float autocvar_g_monster_zombie_health;
5 float autocvar_g_monster_zombie_damageforcescale = 0.55;
6 float autocvar_g_monster_zombie_attack_melee_damage;
7 float autocvar_g_monster_zombie_attack_melee_delay;
8 float autocvar_g_monster_zombie_attack_leap_damage;
9 float autocvar_g_monster_zombie_attack_leap_force;
10 float autocvar_g_monster_zombie_attack_leap_speed;
11 float autocvar_g_monster_zombie_attack_leap_delay;
12 float autocvar_g_monster_zombie_speed_stop;
13 float autocvar_g_monster_zombie_speed_run;
14 float autocvar_g_monster_zombie_speed_walk;
15 
16 /*
17 const float zombie_anim_attackleap = 0;
18 const float zombie_anim_attackrun1 = 1;
19 const float zombie_anim_attackrun2 = 2;
20 const float zombie_anim_attackrun3 = 3;
21 const float zombie_anim_attackstanding1 = 4;
22 const float zombie_anim_attackstanding2 = 5;
23 const float zombie_anim_attackstanding3 = 6;
24 const float zombie_anim_blockend = 7;
25 const float zombie_anim_blockstart = 8;
26 const float zombie_anim_deathback1 = 9;
27 const float zombie_anim_deathback2 = 10;
28 const float zombie_anim_deathback3 = 11;
29 const float zombie_anim_deathfront1 = 12;
30 const float zombie_anim_deathfront2 = 13;
31 const float zombie_anim_deathfront3 = 14;
32 const float zombie_anim_deathleft1 = 15;
33 const float zombie_anim_deathleft2 = 16;
34 const float zombie_anim_deathright1 = 17;
35 const float zombie_anim_deathright2 = 18;
36 const float zombie_anim_idle = 19;
37 const float zombie_anim_painback1 = 20;
38 const float zombie_anim_painback2 = 21;
39 const float zombie_anim_painfront1 = 22;
40 const float zombie_anim_painfront2 = 23;
41 const float zombie_anim_runbackwards = 24;
42 const float zombie_anim_runbackwardsleft = 25;
43 const float zombie_anim_runbackwardsright = 26;
44 const float zombie_anim_runforward = 27;
45 const float zombie_anim_runforwardleft = 28;
46 const float zombie_anim_runforwardright = 29;
47 const float zombie_anim_spawn = 30;
48 */
49 
50 .vector moveto;
51 
52 void M_Zombie_Attack_Leap_Touch(entity this, entity toucher)
53 {
54  if (GetResource(this, RES_HEALTH) <= 0)
55  return;
56 
57  vector angles_face;
58 
59  if(toucher.takedamage)
60  {
61  angles_face = vectoangles(this.moveto - this.origin);
62  angles_face = normalize(angles_face) * (autocvar_g_monster_zombie_attack_leap_force);
63  Damage(toucher, this, this, (autocvar_g_monster_zombie_attack_leap_damage) * MONSTER_SKILLMOD(this), DEATH_MONSTER_ZOMBIE_JUMP.m_id, DMG_NOWEP, toucher.origin, angles_face);
64  settouch(this, Monster_Touch); // instantly turn it off to stop damage spam
65  this.state = 0;
66  }
67 
69  {
70  this.state = 0;
71  settouch(this, Monster_Touch);
72  }
73 }
74 
75 void M_Zombie_Defend_Block_End(entity this)
76 {
77  if(GetResource(this, RES_HEALTH) <= 0)
78  return;
79 
80  setanim(this, this.anim_blockend, false, true, true);
82 }
83 
84 bool M_Zombie_Defend_Block(entity this)
85 {
86  SetResourceExplicit(this, RES_ARMOR, 0.9);
87  this.state = MONSTER_ATTACK_MELEE; // freeze monster
88  this.attack_finished_single[0] = time + 2.1;
90  setanim(this, this.anim_blockstart, false, true, true);
91 
92  Monster_Delay(this, 1, 2, M_Zombie_Defend_Block_End);
93 
94  return true;
95 }
96 
97 bool M_Zombie_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
98 {
99  switch(attack_type)
100  {
102  {
103  if(random() < 0.3 && GetResource(actor, RES_HEALTH) < 75 && GetResource(actor.enemy, RES_HEALTH) > 10)
104  return M_Zombie_Defend_Block(actor);
105 
106  float anim_chance = random();
107  vector chosen_anim;
108 
109  if(anim_chance < 0.33)
110  chosen_anim = actor.anim_melee1;
111  else if(anim_chance < 0.66)
112  chosen_anim = actor.anim_melee2;
113  else
114  chosen_anim = actor.anim_melee3;
115 
116  return Monster_Attack_Melee(actor, actor.enemy, (autocvar_g_monster_zombie_attack_melee_damage), chosen_anim, actor.attack_range, (autocvar_g_monster_zombie_attack_melee_delay), DEATH_MONSTER_ZOMBIE_MELEE.m_id, true);
117  }
119  {
120  makevectors(actor.angles);
121  return Monster_Attack_Leap(actor, actor.anim_shoot, M_Zombie_Attack_Leap_Touch, v_forward * (autocvar_g_monster_zombie_attack_leap_speed) + '0 0 200', (autocvar_g_monster_zombie_attack_leap_delay));
122  }
123  }
124 
125  return false;
126 }
127 
128 spawnfunc(monster_zombie) { Monster_Spawn(this, true, MON_ZOMBIE); }
129 #endif // SVQC
130 
131 #ifdef SVQC
132 METHOD(Zombie, mr_think, bool(Zombie this, entity actor))
133 {
134  TC(Zombie, this);
135  if(time >= actor.spawn_time)
136  actor.damageforcescale = autocvar_g_monster_zombie_damageforcescale;
137  return true;
138 }
139 
140 METHOD(Zombie, mr_pain, float(Zombie this, entity actor, float damage_take, entity attacker, float deathtype))
141 {
142  TC(Zombie, this);
143  actor.pain_finished = time + 0.34;
144  setanim(actor, ((random() > 0.5) ? actor.anim_pain1 : actor.anim_pain2), true, true, false);
145  return damage_take;
146 }
147 
148 METHOD(Zombie, mr_death, bool(Zombie this, entity actor))
149 {
150  TC(Zombie, this);
152 
153  setanim(actor, ((random() > 0.5) ? actor.anim_die1 : actor.anim_die2), false, true, true);
154  return true;
155 }
156 #endif
157 #ifdef GAMEQC
158 METHOD(Zombie, mr_anim, bool(Zombie this, entity actor))
159 {
160  TC(Zombie, this);
161  vector none = '0 0 0';
162  actor.anim_die1 = animfixfps(actor, '9 1 0.5', none); // 2 seconds
163  actor.anim_die2 = animfixfps(actor, '12 1 0.5', none); // 2 seconds
164  actor.anim_spawn = animfixfps(actor, '30 1 3', none);
165  actor.anim_walk = animfixfps(actor, '27 1 1', none);
166  actor.anim_idle = animfixfps(actor, '19 1 1', none);
167  actor.anim_pain1 = animfixfps(actor, '20 1 2', none); // 0.5 seconds
168  actor.anim_pain2 = animfixfps(actor, '22 1 2', none); // 0.5 seconds
169  actor.anim_melee1 = animfixfps(actor, '4 1 5', none); // analyze models and set framerate
170  actor.anim_melee2 = animfixfps(actor, '4 1 5', none); // analyze models and set framerate
171  actor.anim_melee3 = animfixfps(actor, '4 1 5', none); // analyze models and set framerate
172  actor.anim_shoot = animfixfps(actor, '0 1 5', none); // analyze models and set framerate
173  actor.anim_run = animfixfps(actor, '27 1 1', none);
174  actor.anim_blockstart = animfixfps(actor, '8 1 1', none);
175  actor.anim_blockend = animfixfps(actor, '7 1 1', none);
176  return true;
177 }
178 #endif
179 #ifdef SVQC
180 METHOD(Zombie, mr_setup, bool(Zombie this, entity actor))
181 {
182  TC(Zombie, this);
183  if(!GetResource(actor, RES_HEALTH)) SetResourceExplicit(actor, RES_HEALTH, autocvar_g_monster_zombie_health);
184  if(!actor.speed) { actor.speed = (autocvar_g_monster_zombie_speed_walk); }
185  if(!actor.speed2) { actor.speed2 = (autocvar_g_monster_zombie_speed_run); }
186  if(!actor.stopspeed) { actor.stopspeed = (autocvar_g_monster_zombie_speed_stop); }
187 
188  if(actor.spawnflags & MONSTERFLAG_NORESPAWN)
189  actor.spawnflags &= ~MONSTERFLAG_NORESPAWN; // zombies always respawn
190 
191  actor.spawnflags &= ~MONSTERFLAG_APPEAR; // once it's appeared, it will respawn quickly, we don't want it to appear
192 
193  actor.spawnflags |= MONSTER_RESPAWN_DEATHPOINT;
194 
195  actor.monster_loot = ITEM_HealthMedium;
196  actor.monster_attackfunc = M_Zombie_Attack;
197  StatusEffects_apply(STATUSEFFECT_SpawnShield, actor, actor.spawn_time, 0);
198  actor.respawntime = 0.2;
199  actor.damageforcescale = 0.0001; // no push while spawning
200 
201  setanim(actor, actor.anim_spawn, false, true, true);
202  actor.spawn_time = actor.animstate_endtime;
203 
204  return true;
205 }
206 #endif
float state
Definition: subs.qh:32
float anim_finished
Definition: sv_monsters.qh:51
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition: cl_resources.qc:15
#define setanim(...)
Definition: anim.qh:45
bool Monster_Attack_Melee(entity this, entity targ, float damg, vector anim, float er, float animtime, int deathtype, bool dostop)
Definition: sv_monsters.qc:362
vector anim_blockstart
Definition: monster.qh:24
float trace_dphitcontents
entity() spawn
void Monster_Delay(entity this, int repeat_count, float defer_amnt, void(entity) func)
Definition: sv_monsters.qc:218
spawnfunc(info_player_attacker)
Definition: sv_assault.qc:283
origin
Definition: ent_cs.qc:114
const int MONSTERFLAG_NORESPAWN
Definition: sv_monsters.qh:86
#define METHOD(cname, name, prototype)
Definition: oo.qh:257
const int MONSTERFLAG_APPEAR
Definition: sv_monsters.qh:85
#define DMG_NOWEP
Definition: damage.qh:126
bool Monster_Attack_Leap(entity this, vector anm, void(entity this, entity toucher) touchfunc, vector vel, float animtime)
Definition: sv_monsters.qc:403
RES_HEALTH
Definition: ent_cs.qc:126
vector anim_blockend
Definition: monster.qh:23
Definition: zombie.qh:9
#define MONSTER_SKILLMOD(mon)
Definition: sv_monsters.qh:59
const int MONSTER_ATTACK_MELEE
Definition: sv_monsters.qh:70
#define TC(T, sym)
Definition: _all.inc:82
const int MONSTER_ATTACK_RANGED
Definition: sv_monsters.qh:71
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition: damage.qc:583
void Monster_Touch(entity this, entity toucher)
Definition: sv_monsters.qc:479
vector(float skel, float bonenum) _skel_get_boneabs_hidden
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
Definition: cl_resources.qc:10
bool Monster_Spawn(entity this, bool check_appear, Monster mon)
float autocvar_g_monsters_armor_blockpercent
Definition: sv_monsters.qh:28
float time
Definition: csprogsdefs.qc:16
#define makevectors
Definition: post.qh:21
const int MONSTER_RESPAWN_DEATHPOINT
Definition: monster.qh:4
float attack_finished_single[MAX_WEAPONSLOTS]
Definition: weaponsystem.qh:36
vector v_forward
Definition: csprogsdefs.qc:31