Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
golem.qc
Go to the documentation of this file.
1#include "golem.qh"
2
3#ifdef SVQC
5string autocvar_g_monster_golem_loot = "health_mega electro";
21
22.float golem_lastattack; // delay attacks separately
23
25{
26 makevectors(this.angles);
27 Send_Effect(EFFECT_EXPLOSION_MEDIUM, (this.origin + (v_forward * 150)) - ('0 0 1' * this.maxs.z), '0 0 0', 1);
28 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
29
30 vector loc = this.origin + v_forward * 50;
31
32 entity dmgent = spawn();
33 dmgent.owner = dmgent.realowner = this;
34 setorigin(dmgent, loc);
37 delete(dmgent);
38}
39
41{
42 Monster_Attack_Melee(this, this.enemy, (autocvar_g_monster_golem_attack_claw_damage), ((random() >= 0.5) ? this.anim_melee2 : this.anim_melee3), this.attack_range, 0.8, DEATH_MONSTER_GOLEM_CLAW.m_id, true);
43}
44
46
48{
49 sound(this, CH_SHOTS, SND_MON_GOLEM_LIGHTNING_IMPACT, VOL_BASE, ATTEN_NORM);
50 Send_Effect(EFFECT_ELECTRO_IMPACT, this.origin, '0 0 0', 1);
51
52 this.event_damage = func_null;
53 this.takedamage = DAMAGE_NO;
55 this.velocity = '0 0 0';
56
58 this.velocity = this.oldvelocity;
59
62
64 {
65 te_csqc_lightningarc(this.origin, it.origin);
66 Damage(it, this, this.realowner, (autocvar_g_monster_golem_attack_lightning_damage_zap) * MONSTER_SKILLMOD(this), DEATH_MONSTER_GOLEM_ZAP.m_id, DMG_NOWEP, it.origin, '0 0 0');
67 });
68
69 setthink(this, SUB_Remove);
70 this.nextthink = time + 0.2;
71}
72
77
78void M_Golem_Attack_Lightning_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
79{
80 if (GetResource(this, RES_HEALTH) <= 0)
81 return;
82
83 if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions
84 return; // g_projectiles_damage says to halt
85
86 TakeResource(this, RES_HEALTH, damage);
87
88 if (GetResource(this, RES_HEALTH) <= 0)
89 W_PrepareExplosionByDamage(this, attacker, adaptor_think2use);
90}
91
93{
95
96 this.use(this, NULL, toucher);
97}
98
100{
101 this.nextthink = time;
102 if (time > this.cnt)
103 {
105 return;
106 }
107}
108
110{
111 entity gren;
112
113 monster_makevectors(this, this.enemy);
114
115 gren = new(grenade);
116 gren.owner = gren.realowner = this;
117 gren.bot_dodge = true;
121 gren.projectiledeathtype = DEATH_MONSTER_GOLEM_ZAP.m_id;
122 setorigin(gren, CENTER_OR_VIEWOFS(this));
123 setsize(gren, '-8 -8 -8', '8 8 8');
124 gren.scale = 2.5;
125
126 gren.cnt = time + 5;
127 gren.nextthink = time;
131
132 gren.takedamage = DAMAGE_YES;
133 SetResourceExplicit(gren, RES_HEALTH, 50);
134 gren.damageforcescale = 0;
135 gren.event_damage = M_Golem_Attack_Lightning_Damage;
136 gren.damagedbycontents = true;
138 gren.missile_flags = MIF_SPLASH | MIF_ARC;
140
141 gren.angles = vectoangles (gren.velocity);
142 gren.flags = FL_PROJECTILE;
143 IL_PUSH(g_projectiles, gren);
144 IL_PUSH(g_bot_dodge, gren);
145
147}
148
149.int state;
150
151bool M_Golem_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
152{
153 switch(attack_type)
154 {
156 {
157 setanim(actor, ((random() >= 0.5) ? actor.anim_melee2 : actor.anim_melee3), false, true, true);
158 int swing_cnt = bound(1, floor(random() * 4), 3);
159 Monster_Delay(actor, swing_cnt, 0.5, M_Golem_Attack_Swing);
160 actor.anim_finished = actor.attack_finished_single[0] = time + (0.5 * swing_cnt); // set this for the delay
161 return true;
162 }
164 {
165 float randomness = random();
166
167 if(time < actor.golem_lastattack || !IS_ONGROUND(actor))
168 return false;
169
170 if(randomness <= 0.5 && vdist(actor.enemy.origin - actor.origin, <=, autocvar_g_monster_golem_attack_smash_range))
171 {
172 setanim(actor, actor.anim_melee1, false, true, true);
173 Monster_Delay(actor, 1, 1.1, M_Golem_Attack_Smash);
174 if(actor.animstate_endtime > time)
175 actor.anim_finished = actor.animstate_endtime;
176 else
177 actor.anim_finished = time + 1.2;
178 actor.attack_finished_single[0] = actor.anim_finished + 0.2;
179 actor.state = MONSTER_ATTACK_MELEE; // kinda a melee attack
180 actor.golem_lastattack = time + 3 + random() * 1.5;
181 return true;
182 }
183 else if(randomness <= 0.1 && vdist(actor.enemy.origin - actor.origin, >=, autocvar_g_monster_golem_attack_smash_range * 1.5)) // small chance, don't want this spammed
184 {
185 setanim(actor, actor.anim_melee2, true, true, false);
186 actor.state = MONSTER_ATTACK_MELEE; // maybe we should rename this to something more general
187 actor.attack_finished_single[0] = time + 1.1;
188 actor.anim_finished = 1.1;
189 actor.golem_lastattack = time + 3 + random() * 1.5;
191 return true;
192 }
193
194 return false;
195 }
196 }
197
198 return false;
199}
200
201spawnfunc(monster_golem) { Monster_Spawn(this, true, MON_GOLEM); }
202// compatibility
203spawnfunc(monster_shambler) { spawnfunc_monster_golem(this); }
204#endif // SVQC
205
206#ifdef SVQC
207METHOD(Golem, mr_think, bool(Golem this, entity actor))
208{
209 TC(Golem, this);
210 return true;
211}
212
213METHOD(Golem, mr_pain, float(Golem this, entity actor, float damage_take, entity attacker, float deathtype))
214{
215 TC(Golem, this);
216 actor.pain_finished = time + 0.5;
217 setanim(actor, ((random() >= 0.5) ? actor.anim_pain2 : actor.anim_pain1), true, true, false);
218 return damage_take;
219}
220
221METHOD(Golem, mr_death, bool(Golem this, entity actor))
222{
223 TC(Golem, this);
224 setanim(actor, actor.anim_die1, false, true, true);
225 return true;
226}
227#endif
228#ifdef GAMEQC
229METHOD(Golem, mr_anim, bool(Golem this, entity actor))
230{
231 TC(Golem, this);
232 vector none = '0 0 0';
233 actor.anim_idle = animfixfps(actor, '0 1 1', none);
234 actor.anim_walk = animfixfps(actor, '1 1 1', none);
235 actor.anim_run = animfixfps(actor, '2 1 1', none);
236 //actor.anim_melee1 = animfixfps(actor, '3 1 5', none); // analyze models and set framerate
237 actor.anim_melee2 = animfixfps(actor, '4 1 5', none); // analyze models and set framerate
238 actor.anim_melee3 = animfixfps(actor, '5 1 5', none); // analyze models and set framerate
239 //actor.anim_melee4 = animfixfps(actor, '6 1 5', none); // analyze models and set framerate
240 actor.anim_melee1 = animfixfps(actor, '6 1 5', none); // analyze models and set framerate
241 actor.anim_pain1 = animfixfps(actor, '7 1 2', none); // 0.5 seconds
242 actor.anim_pain2 = animfixfps(actor, '8 1 2', none); // 0.5 seconds
243 //actor.anim_pain3 = animfixfps(actor, '9 1 2', none); // 0.5 seconds
244 //actor.anim_pain4 = animfixfps(actor, '10 1 2', none); // 0.5 seconds
245 //actor.anim_pain5 = animfixfps(actor, '11 1 2', none); // 0.5 seconds
246 actor.anim_spawn = animfixfps(actor, '12 1 5', none); // analyze models and set framerate
247 actor.anim_die1 = animfixfps(actor, '13 1 0.5', none); // 2 seconds
248 //actor.anim_dead = animfixfps(actor, '14 1 0.5', none); // 2 seconds
249 actor.anim_die2 = animfixfps(actor, '15 1 0.5', none); // 2 seconds
250 // dead2 16
251 //actor.anim_dieback = animfixfps(actor, '16 1 0.5', none); // 2 seconds
252 //actor.anim_deadback = animfixfps(actor, '17 1 0.5', none); // 2 seconds
253 //actor.anim_dead2 = animfixfps(actor, '18 1 0.5', none); // 2 seconds
254 //actor.anim_dead3 = animfixfps(actor, '19 1 0.5', none); // 2 seconds
255 //actor.anim_dead4 = animfixfps(actor, '20 1 0.5', none); // 2 seconds
256 //actor.anim_dead5 = animfixfps(actor, '21 1 0.5', none); // 2 seconds
257 //actor.anim_dead6 = animfixfps(actor, '22 1 0.5', none); // 2 seconds
258 return true;
259}
260#endif
261#ifdef SVQC
263METHOD(Golem, mr_setup, bool(Golem this, entity actor))
264{
265 TC(Golem, this);
266 if(!GetResource(actor, RES_HEALTH)) SetResourceExplicit(actor, RES_HEALTH, autocvar_g_monster_golem_health);
267 if(!actor.attack_range) actor.attack_range = 150;
268 if(!actor.speed) { actor.speed = (autocvar_g_monster_golem_speed_walk); }
269 if(!actor.speed2) { actor.speed2 = (autocvar_g_monster_golem_speed_run); }
270 if(!actor.stopspeed) { actor.stopspeed = (autocvar_g_monster_golem_speed_stop); }
271 if(!actor.damageforcescale) { actor.damageforcescale = (autocvar_g_monster_golem_damageforcescale); }
272
273 actor.monster_loot = autocvar_g_monster_golem_loot;
274
275 setanim(actor, actor.anim_spawn, false, true, true);
276 actor.spawn_time = actor.animstate_endtime;
277 StatusEffects_apply(STATUSEFFECT_SpawnShield, actor, actor.spawn_time, 0);
278 actor.monster_attackfunc = M_Golem_Attack;
279
280 return true;
281}
282#endif
283#ifdef MENUQC
284METHOD(Golem, describe, string(Golem this))
285{
286 TC(Golem, this);
288 PAR(_("Golems are large powerful brutes capable of taking and dealing a beating. Keeping your distance is advised."));
289 PAR(_("The Golem's primary melee attack is a series of punches. "
290 "On occasion the Golem may jump into the air, dealing massive damage in an area as it slams the ground."));
291 PAR(_("To deal with distant foes, the Golem may throw a chunk of its electrified rocky exterior, zapping nearby targets on impact."));
292 return PAGE_TEXT;
293}
294#endif
float animstate_endtime
Definition anim.qh:38
#define setanim(...)
Definition anim.qh:45
IntrusiveList g_bot_dodge
Definition api.qh:150
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.
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition golem.qh:9
float cnt
Definition powerups.qc:24
const int FL_PROJECTILE
Definition constants.qh:85
vector v_up
vector velocity
float time
vector maxs
float nextthink
vector v_forward
vector origin
#define spawn
#define use
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
Definition damage.qc:981
IntrusiveList g_damagedbycontents
Definition damage.qh:135
#define DMG_NOWEP
Definition damage.qh:104
int state
void SUB_Remove(entity this)
Remove entity.
Definition defer.qh:13
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:124
ent angles
Definition ent_cs.qc:121
void M_Golem_Attack_Lightning_Explode(entity this, entity directhitentity)
Definition golem.qc:47
float autocvar_g_monster_golem_attack_lightning_force
Definition golem.qc:13
void M_Golem_Attack_Lightning_Explode_use(entity this, entity actor, entity trigger)
Definition golem.qc:73
float autocvar_g_monster_golem_attack_lightning_damage
Definition golem.qc:11
float autocvar_g_monster_golem_attack_lightning_radius_zap
Definition golem.qc:15
string autocvar_g_monster_golem_loot
Definition golem.qc:5
float autocvar_g_monster_golem_speed_walk
Definition golem.qc:20
float golem_lastattack
Definition golem.qc:22
void M_Golem_Attack_Lightning_Touch(entity this, entity toucher)
Definition golem.qc:92
float autocvar_g_monster_golem_attack_lightning_damage_zap
Definition golem.qc:12
void M_Golem_Attack_Lightning_Think(entity this)
Definition golem.qc:99
float autocvar_g_monster_golem_attack_lightning_radius
Definition golem.qc:14
float autocvar_g_monster_golem_attack_smash_range
Definition golem.qc:9
float autocvar_g_monster_golem_health
Definition golem.qc:4
float autocvar_g_monster_golem_speed_stop
Definition golem.qc:18
float autocvar_g_monster_golem_attack_claw_damage
Definition golem.qc:10
float autocvar_g_monster_golem_attack_lightning_speed_up
Definition golem.qc:17
float autocvar_g_monster_golem_damageforcescale
Definition golem.qc:6
void M_Golem_Attack_Smash(entity this)
Definition golem.qc:24
float autocvar_g_monster_golem_attack_smash_damage
Definition golem.qc:7
float autocvar_g_monster_golem_attack_lightning_speed
Definition golem.qc:16
float autocvar_g_monster_golem_speed_run
Definition golem.qc:19
void M_Golem_Attack_Swing(entity this)
Definition golem.qc:40
void M_Golem_Attack_Lightning(entity this)
Definition golem.qc:109
float autocvar_g_monster_golem_attack_smash_force
Definition golem.qc:8
bool M_Golem_Attack(int attack_type, entity actor, entity targ,.entity weaponentity)
Definition golem.qc:151
void M_Golem_Attack_Lightning_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition golem.qc:78
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define FOREACH_ENTITY_RADIUS(org, dist, cond, body)
Definition iter.qh:160
#define TC(T, sym)
Definition _all.inc:82
float bound(float min, float value, float max)
float random(void)
vector vectoangles(vector v)
float floor(float f)
vector anim_melee2
Definition monster.qh:30
vector animfixfps(entity e, vector a, vector b)
Definition util.qc:1808
vector anim_melee3
Definition monster.qh:31
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_NONE
Definition movetypes.qh:129
float move_movetype
Definition movetypes.qh:76
const int MOVETYPE_BOUNCE
Definition movetypes.qh:139
#define IS_ONGROUND(s)
Definition movetypes.qh:16
var void func_null()
#define METHOD(cname, name, prototype)
Definition oo.qh:269
#define NULL
Definition post.qh:14
#define makevectors
Definition post.qh:21
const int PROJECTILE_GOLEM_LIGHTNING
#define setthink(e, f)
vector
Definition self.qh:92
entity entity toucher
Definition self.qh:72
#define settouch(e, f)
Definition self.qh:73
vector oldvelocity
Definition main.qh:42
float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception)
Definition common.qc:45
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
Definition common.qc:87
const int MIF_SPLASH
Definition common.qh:46
int projectiledeathtype
Definition common.qh:21
#define PROJECTILE_TOUCH(e, t)
Definition common.qh:28
IntrusiveList g_projectiles
Definition common.qh:58
const int MIF_ARC
Definition common.qh:47
#define PROJECTILE_MAKETRIGGER(e)
Definition common.qh:34
const float VOL_BASE
Definition sound.qh:36
const int CH_SHOTS
Definition sound.qh:14
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
#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
const int DAMAGE_YES
Definition subs.qh:80
const int DAMAGE_NO
Definition subs.qh:79
float takedamage
Definition subs.qh:78
entity enemy
Definition sv_ctf.qh:153
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_makevectors(entity this, entity targ)
bool Monster_Attack_Melee(entity this, entity targ, float damg, vector anim, float er, float animtime, int deathtype, bool dostop)
#define MONSTER_SKILLMOD(mon)
float attack_range
const int MONSTER_ATTACK_MELEE
const int MONSTER_ATTACK_RANGED
entity realowner
void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute)
Definition tracing.qc:192
#define CENTER_OR_VIEWOFS(ent)
Definition utils.qh:29
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8