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
17.vector moveto;
18
20{
21 if (GetResource(this, RES_HEALTH) <= 0)
22 return;
23
24 vector angles_face;
25
26 if(toucher.takedamage)
27 {
28 angles_face = vectoangles(this.moveto - this.origin);
29 angles_face = normalize(angles_face) * (autocvar_g_monster_zombie_attack_leap_force);
30 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);
31 settouch(this, Monster_Touch); // instantly turn it off to stop damage spam
32 this.state = 0;
33 }
34
36 {
37 this.state = 0;
39 }
40}
41
43{
44 if(GetResource(this, RES_HEALTH) <= 0)
45 return;
46
47 setanim(this, this.anim_blockend, false, true, true);
49}
50
52{
54 this.state = MONSTER_ATTACK_MELEE; // freeze monster
55 this.attack_finished_single[0] = time + 2.1;
57 setanim(this, this.anim_blockstart, false, true, true);
58
60
61 return true;
62}
63
64bool M_Zombie_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
65{
66 switch(attack_type)
67 {
69 {
70 if(random() < 0.3 && GetResource(actor, RES_HEALTH) < 75 && GetResource(actor.enemy, RES_HEALTH) > 10)
71 return M_Zombie_Defend_Block(actor);
72
73 float anim_chance = random();
74 vector chosen_anim;
75
76 if(anim_chance < 0.33)
77 chosen_anim = actor.anim_melee1;
78 else if(anim_chance < 0.66)
79 chosen_anim = actor.anim_melee2;
80 else
81 chosen_anim = actor.anim_melee3;
82
83 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);
84 }
86 {
87 makevectors(actor.angles);
89 }
90 }
91
92 return false;
93}
94
95spawnfunc(monster_zombie) { Monster_Spawn(this, true, MON_ZOMBIE); }
96#endif // SVQC
97
98#ifdef SVQC
99METHOD(Zombie, mr_think, bool(Zombie this, entity actor))
100{
101 TC(Zombie, this);
102 if(time >= actor.spawn_time)
103 actor.damageforcescale = autocvar_g_monster_zombie_damageforcescale;
104 return true;
105}
106
107METHOD(Zombie, mr_pain, float(Zombie this, entity actor, float damage_take, entity attacker, float deathtype))
108{
109 TC(Zombie, this);
110 actor.pain_finished = time + 0.34;
111 if(time >= actor.spawn_time)
112 setanim(actor, ((random() > 0.5) ? actor.anim_pain1 : actor.anim_pain2), true, true, false);
113 return damage_take;
114}
115
116METHOD(Zombie, mr_death, bool(Zombie this, entity actor))
117{
118 TC(Zombie, this);
120
121 setanim(actor, ((random() > 0.5) ? actor.anim_die1 : actor.anim_die2), false, true, true);
122 return true;
123}
124#endif
125#ifdef GAMEQC
126METHOD(Zombie, mr_anim, bool(Zombie this, entity actor))
127{
128 TC(Zombie, this);
129 vector none = '0 0 0';
130 actor.anim_die1 = animfixfps(actor, '9 1 0.5', none); // 2 seconds
131 actor.anim_die2 = animfixfps(actor, '12 1 0.5', none); // 2 seconds
132 actor.anim_spawn = animfixfps(actor, '30 1 3', none);
133 actor.anim_walk = animfixfps(actor, '27 1 1', none);
134 actor.anim_idle = animfixfps(actor, '19 1 1', none);
135 actor.anim_pain1 = animfixfps(actor, '20 1 2', none); // 0.5 seconds
136 actor.anim_pain2 = animfixfps(actor, '22 1 2', none); // 0.5 seconds
137 actor.anim_melee1 = animfixfps(actor, '4 1 5', none); // analyze models and set framerate
138 actor.anim_melee2 = animfixfps(actor, '4 1 5', none); // analyze models and set framerate
139 actor.anim_melee3 = animfixfps(actor, '4 1 5', none); // analyze models and set framerate
140 actor.anim_shoot = animfixfps(actor, '0 1 5', none); // analyze models and set framerate
141 actor.anim_run = animfixfps(actor, '27 1 1', none);
142 actor.anim_blockstart = animfixfps(actor, '8 1 1', none);
143 actor.anim_blockend = animfixfps(actor, '7 1 1', none);
144 return true;
145}
146#endif
147#ifdef SVQC
148METHOD(Zombie, mr_setup, bool(Zombie this, entity actor))
149{
150 TC(Zombie, this);
151 if(!GetResource(actor, RES_HEALTH)) SetResourceExplicit(actor, RES_HEALTH, autocvar_g_monster_zombie_health);
152 if(!actor.speed) { actor.speed = (autocvar_g_monster_zombie_speed_walk); }
153 if(!actor.speed2) { actor.speed2 = (autocvar_g_monster_zombie_speed_run); }
154 if(!actor.stopspeed) { actor.stopspeed = (autocvar_g_monster_zombie_speed_stop); }
155
156 if(actor.spawnflags & MONSTERFLAG_NORESPAWN)
157 actor.spawnflags &= ~MONSTERFLAG_NORESPAWN; // zombies always respawn
158
159 actor.spawnflags &= ~MONSTERFLAG_APPEAR; // once it's appeared, it will respawn quickly, we don't want it to appear
160
161 actor.spawnflags |= MONSTER_RESPAWN_DEATHPOINT;
162
163 actor.monster_loot = autocvar_g_monster_zombie_loot;
164 actor.monster_attackfunc = M_Zombie_Attack;
165 StatusEffects_apply(STATUSEFFECT_SpawnShield, actor, actor.spawn_time, 0);
166 actor.respawntime = 0.2;
167 actor.damageforcescale = 0.0001; // no push while spawning
168
169 setanim(actor, actor.anim_spawn, false, true, true);
170 actor.spawn_time = actor.animstate_endtime;
171
172 return true;
173}
174#endif
175#ifdef MENUQC
176METHOD(Zombie, describe, string(Zombie this))
177{
178 TC(Zombie, this);
180 PAR(_("Zombies are the undead remains of deceased soldiers, risen with a ravenous hunger and no sense of self-preservation."));
181 PAR(_("When a Zombie senses a nearby player it will begin to charge its target at high speeds. "
182 "While charging, a Zombie may leap towards the player, dealing massive damage on contact. "
183 "If it gets close, the Zombie will punch and bite repeatedly."));
184 PAR(_("When threatened the Zombie may hold up its hands to block incoming attacks briefly."));
185 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!"));
186 return PAGE_TEXT;
187}
188#endif
#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:503
#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:27
const int MONSTER_RESPAWN_DEATHPOINT
Definition monster.qh:8
vector anim_blockstart
Definition monster.qh:28
vector animfixfps(entity e, vector a, vector b)
Definition util.qc:1808
#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:643
#define PAR(...)
Adds an individually translatable paragraph to PAGE_TEXT without having to deal with strcat and sprin...
Definition string.qh:649
#define PAGE_TEXT_INIT()
Definition string.qh:642
void Monster_Delay(entity this, int repeat_count, float defer_amnt, void(entity) func)
bool Monster_Spawn(entity this, bool check_appear, Monster mon)
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
#define MONSTER_SKILLMOD(mon)
float anim_finished
const int MONSTERFLAG_APPEAR
const int MONSTER_ATTACK_MELEE
const int MONSTER_ATTACK_RANGED
float autocvar_g_monsters_armor_blockpercent
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:19
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:51
void M_Zombie_Defend_Block_End(entity this)
Definition zombie.qc:42
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:64
string autocvar_g_monster_zombie_loot
Definition zombie.qc:5
vector moveto
Definition zombie.qc:17