Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
zombie.qc
Go to the documentation of this file.
1#include "zombie.qh"
2
3#ifdef SVQC
5string autocvar_g_monster_zombie_loot = "health_medium";
16
18{
19 if (GetResource(this, RES_HEALTH) <= 0)
20 return;
21
22 vector angles_face;
23
24 if (toucher.takedamage)
25 {
26 angles_face = vectoangles(this.moveto - this.origin);
27 angles_face = normalize(angles_face) * autocvar_g_monster_zombie_attack_leap_force;
28 Damage(toucher, this, this.realowner,
30 DEATH_MONSTER_ZOMBIE_JUMP.m_id,
32 toucher.origin,
33 angles_face
34 );
35 settouch(this, Monster_Touch); // instantly turn it off to stop damage spam
36 this.state = 0;
37 }
38
40 {
41 this.state = 0;
43 }
44}
45
47{
48 if (GetResource(this, RES_HEALTH) <= 0)
49 return;
50
51 setanim(this, this.anim_blockend, false, true, true);
53}
54
56{
58 this.state = MONSTER_ATTACK_MELEE; // freeze monster
59 this.attack_finished_single[0] = time + 2.1;
61 setanim(this, this.anim_blockstart, false, true, true);
62
64
65 return true;
66}
67
68bool M_Zombie_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
69{
70 switch (attack_type)
71 {
73 {
74 if (random() < 0.3 && GetResource(actor, RES_HEALTH) < 75 && GetResource(actor.enemy, RES_HEALTH) > 10)
75 return M_Zombie_Defend_Block(actor);
76
77 float anim_chance = random();
78 vector chosen_anim;
79 if (anim_chance < 0.33)
80 chosen_anim = actor.anim_melee1;
81 else if (anim_chance < 0.66)
82 chosen_anim = actor.anim_melee2;
83 else
84 chosen_anim = actor.anim_melee3;
85
86 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);
87 }
89 makevectors(actor.angles);
91 }
92 return false;
93}
94
95spawnfunc(monster_zombie)
96{
97 Monster_Spawn(this, true, MON_ZOMBIE);
98}
99
100METHOD(Zombie, mr_think, bool(Zombie this, entity actor))
101{
102 TC(Zombie, this);
103 if (time >= actor.spawn_time)
104 actor.damageforcescale = autocvar_g_monster_zombie_damageforcescale;
105 return true;
106}
107
108METHOD(Zombie, mr_pain, float(Zombie this, entity actor, float damage_take, entity attacker, float deathtype))
109{
110 TC(Zombie, this);
111 actor.pain_finished = time + 0.34;
112 if (time >= actor.spawn_time)
113 setanim(actor, ((random() > 0.5) ? actor.anim_pain1 : actor.anim_pain2), true, true, false);
114 return damage_take;
115}
116
117METHOD(Zombie, mr_death, bool(Zombie this, entity actor))
118{
119 TC(Zombie, this);
121
122 setanim(actor, ((random() > 0.5) ? actor.anim_die1 : actor.anim_die2), false, true, true);
123 return true;
124}
125#endif // SVQC
126#ifdef GAMEQC
127METHOD(Zombie, mr_anim, bool(Zombie this, entity actor))
128{
129 TC(Zombie, this);
130 vector none = '0 0 0';
131 actor.anim_die1 = animfixfps(actor, '9 1 0.5', none); // 2 seconds
132 actor.anim_die2 = animfixfps(actor, '12 1 0.5', none); // 2 seconds
133 actor.anim_spawn = animfixfps(actor, '30 1 3', none);
134 actor.anim_walk = animfixfps(actor, '27 1 1', none);
135 actor.anim_idle = animfixfps(actor, '19 1 1', none);
136 actor.anim_pain1 = animfixfps(actor, '20 1 2', none); // 0.5 seconds
137 actor.anim_pain2 = animfixfps(actor, '22 1 2', none); // 0.5 seconds
138 actor.anim_melee1 = animfixfps(actor, '4 1 5', none); // analyze models and set framerate
139 actor.anim_melee2 = animfixfps(actor, '4 1 5', none); // analyze models and set framerate
140 actor.anim_melee3 = animfixfps(actor, '4 1 5', none); // analyze models and set framerate
141 actor.anim_shoot = animfixfps(actor, '0 1 5', none); // analyze models and set framerate
142 actor.anim_run = animfixfps(actor, '27 1 1', none);
143 actor.anim_blockstart = animfixfps(actor, '8 1 1', none);
144 actor.anim_blockend = animfixfps(actor, '7 1 1', none);
145 return true;
146}
147#endif // GAMEQC
148#ifdef SVQC
149METHOD(Zombie, mr_setup, bool(Zombie this, entity actor))
150{
151 TC(Zombie, this);
152 if (!GetResource(actor, RES_HEALTH))
154 if (!actor.speed) actor.speed = autocvar_g_monster_zombie_speed_walk;
155 if (!actor.speed2) actor.speed2 = autocvar_g_monster_zombie_speed_run;
156 if (!actor.stopspeed) actor.stopspeed = autocvar_g_monster_zombie_speed_stop;
157
158 if (actor.spawnflags & MONSTERFLAG_NORESPAWN)
159 actor.spawnflags &= ~MONSTERFLAG_NORESPAWN; // zombies always respawn
160
161 actor.spawnflags &= ~MONSTERFLAG_APPEAR; // once it's appeared, it will respawn quickly, we don't want it to appear
162
163 actor.spawnflags |= MONSTER_RESPAWN_DEATHPOINT;
164
165 actor.monster_loot = autocvar_g_monster_zombie_loot;
166 actor.monster_attackfunc = M_Zombie_Attack;
167 StatusEffects_apply(STATUSEFFECT_SpawnShield, actor, actor.spawn_time, 0);
168 actor.respawntime = 0.2;
169 actor.damageforcescale = 0.0001; // no push while spawning
170
171 setanim(actor, actor.anim_spawn, false, true, true);
172 actor.spawn_time = actor.animstate_endtime;
173
174 return true;
175}
176#endif // SVQC
177#ifdef MENUQC
178METHOD(Zombie, describe, string(Zombie this))
179{
180 TC(Zombie, this);
182 PAR(_("Zombies are the undead remains of deceased soldiers, risen with a ravenous hunger and no sense of self-preservation."));
183 PAR(_("When a Zombie senses a nearby player it will begin to charge its target at high speeds. "
184 "While charging, a Zombie may leap towards the player, dealing massive damage on contact. "
185 "If it gets close, the Zombie will punch and bite repeatedly."));
186 PAR(_("When threatened the Zombie may hold up its hands to block incoming attacks briefly."));
187 PAR(_("It is no small task to kill that which is already dead. Once a Zombie is defeated, destroy its corpse to prevent it from rising again!"));
188 return PAGE_TEXT;
189}
190#endif // MENUQC
#define setanim(...)
Definition anim.qh:45
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
float trace_dphitcontents
float time
vector v_forward
vector origin
void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition damage.qc:493
#define DMG_NOWEP
Definition damage.qh:104
int state
RES_ARMOR
Definition ent_cs.qc:130
#define TC(T, sym)
Definition _all.inc:82
float random(void)
vector vectoangles(vector v)
vector normalize(vector v)
vector anim_blockend
Definition monster.qh:26
const int MONSTER_RESPAWN_DEATHPOINT
re-spawn where we died
Definition monster.qh:5
vector anim_blockstart
Definition monster.qh:27
vector animfixfps(entity e, vector a, vector b)
Definition util.qc:1905
vector moveto
Definition movelib.qc:4
#define METHOD(cname, name, prototype)
Definition oo.qh:269
#define makevectors
Definition post.qh:21
vector
Definition self.qh:92
entity entity toucher
Definition self.qh:72
#define settouch(e, f)
Definition self.qh:73
#define spawnfunc(id)
Definition spawnfunc.qh:96
void StatusEffects_apply(StatusEffect this, entity actor, float eff_time, int eff_flags)
#define PAGE_TEXT
Definition string.qh:642
#define PAR(...)
Adds an individually translatable paragraph to PAGE_TEXT without having to deal with strcat and sprin...
Definition string.qh:648
#define PAGE_TEXT_INIT()
Definition string.qh:641
void Monster_Delay(entity this, int repeat_count, float defer_amnt, void(entity) func)
bool Monster_Spawn(entity this, bool check_appear, Monster mon)
Setup the basic required properties for a monster.
void Monster_Touch(entity this, entity toucher)
bool Monster_Attack_Melee(entity this, entity targ, float damg, vector anim, float er, float animtime, int deathtype, bool dostop)
bool Monster_Attack_Leap(entity this, vector anm, void(entity this, entity toucher) touchfunc, vector vel, float animtime)
const int MONSTERFLAG_NORESPAWN
monster doesn't respawn (revive)
#define MONSTER_SKILLMOD(mon)
float anim_finished
will be phased out when we have proper animations system
const int MONSTERFLAG_APPEAR
delay monster spawn until triggered
const int MONSTER_ATTACK_MELEE
const int MONSTER_ATTACK_RANGED
float autocvar_g_monsters_armor_blockpercent
entity realowner
float attack_finished_single[MAX_WEAPONSLOTS]
float autocvar_g_monster_zombie_attack_leap_damage
Definition zombie.qc:9
float autocvar_g_monster_zombie_health
Definition zombie.qc:4
void M_Zombie_Attack_Leap_Touch(entity this, entity toucher)
Definition zombie.qc:17
float autocvar_g_monster_zombie_attack_melee_delay
Definition zombie.qc:8
float autocvar_g_monster_zombie_damageforcescale
Definition zombie.qc:6
float autocvar_g_monster_zombie_speed_run
Definition zombie.qc:14
float autocvar_g_monster_zombie_attack_leap_force
Definition zombie.qc:10
float autocvar_g_monster_zombie_attack_leap_delay
Definition zombie.qc:12
float autocvar_g_monster_zombie_speed_stop
Definition zombie.qc:13
float autocvar_g_monster_zombie_attack_melee_damage
Definition zombie.qc:7
bool M_Zombie_Defend_Block(entity this)
Definition zombie.qc:55
void M_Zombie_Defend_Block_End(entity this)
Definition zombie.qc:46
float autocvar_g_monster_zombie_attack_leap_speed
Definition zombie.qc:11
float autocvar_g_monster_zombie_speed_walk
Definition zombie.qc:15
bool M_Zombie_Attack(int attack_type, entity actor, entity targ,.entity weaponentity)
Definition zombie.qc:68
string autocvar_g_monster_zombie_loot
Definition zombie.qc:5