Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
crylink.qc File Reference
#include "crylink.qh"
#include <common/items/item/ammo.qh>
Include dependency graph for crylink.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void W_Crylink_Attack (Weapon thiswep, entity actor,.entity weaponentity)
void W_Crylink_Attack2 (Weapon thiswep, entity actor,.entity weaponentity)
void W_Crylink_CheckLinks (entity e)
void W_Crylink_DeleteLink (entity this)
void W_Crylink_Dequeue (entity e)
void W_Crylink_Dequeue_Raw (entity own, entity prev, entity me, entity next)
void W_Crylink_Fadethink (entity this)
void W_Crylink_LinkExplode (entity e, entity e2, entity directhitentity)
vector W_Crylink_LinkJoin (entity e, float jspeed)
void W_Crylink_LinkJoinEffect_Think (entity this)
void W_Crylink_Reset (entity this)
void W_Crylink_Touch (entity this, entity toucher)
bool W_Crylink_Touch_WouldHitFriendly (entity projectile, float rad)
bool W_Crylink_Touch_WouldHitFriendly_cond (entity e)

Variables

float w_crylink_linkjoin_time

Function Documentation

◆ W_Crylink_Attack()

void W_Crylink_Attack ( Weapon thiswep,
entity actor,
.entity weaponentity )

Definition at line 285 of file crylink.qc.

286{
287 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(WEP_CRYLINK, ammo), weaponentity);
288
289 float maxdmg = WEP_CVAR_PRI(WEP_CRYLINK, damage) * WEP_CVAR_PRI(WEP_CRYLINK, shots);
290 maxdmg *= 1 + WEP_CVAR_PRI(WEP_CRYLINK, bouncedamagefactor) * WEP_CVAR_PRI(WEP_CRYLINK, bounces);
291 if (WEP_CVAR_PRI(WEP_CRYLINK, joinexplode))
292 maxdmg += WEP_CVAR_PRI(WEP_CRYLINK, joinexplode_damage);
293
294 W_SetupShot(actor, weaponentity, false, 2, SND_CRYLINK_FIRE, CH_WEAPON_A, maxdmg, thiswep.m_id);
295 vector right = v_right;
296 vector up = v_up;
297
298 int shots = WEP_CVAR_PRI(WEP_CRYLINK, shots);
299 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
300 entity proj = NULL, prevproj = NULL, firstproj = NULL;
301 vector s;
302 for (int counter = 0; counter < shots; ++counter)
303 {
304 proj = new(spike);
305 WarpZone_RefSys_Copy(proj, actor);
306 proj.dtor = W_Crylink_DeleteLink;
307 proj.reset = W_Crylink_Reset;
308 proj.realowner = proj.owner = actor;
309 proj.crylink_owner = actor;
310 proj.weaponentity_fld = weaponentity;
311 proj.bot_dodge = true;
312 proj.bot_dodgerating = WEP_CVAR_PRI(WEP_CRYLINK, damage);
313 if (shots == 1)
314 {
315 proj.queuenext = proj;
316 proj.queueprev = proj;
317 }
318 else if (counter == 0) // first projectile, store in firstproj for now
319 firstproj = proj;
320 else if (counter == shots - 1) // last projectile, link up with first projectile
321 {
322 prevproj.queuenext = proj;
323 firstproj.queueprev = proj;
324 proj.queuenext = firstproj;
325 proj.queueprev = prevproj;
326 }
327 else // else link up with previous projectile
328 {
329 prevproj.queuenext = proj;
330 proj.queueprev = prevproj;
331 }
332
333 prevproj = proj;
334
337 proj.projectiledeathtype = thiswep.m_id;
338 //proj.gravity = 0.001;
339
340 setorigin(proj, w_shotorg);
341 setsize(proj, '0 0 0', '0 0 0');
342
343 s = W_CalculateSpreadPattern(1, 0, counter, shots) * WEP_CVAR_PRI(WEP_CRYLINK, spread) * autocvar_g_weaponspreadfactor;
344 W_SetupProjVelocity_Explicit(proj, w_shotdir + right * s.y + up * s.z, v_up, WEP_CVAR_PRI(WEP_CRYLINK, speed), 0, 0, 0, false);
346
348 if (counter == 0)
349 {
350 proj.fade_time = time + WEP_CVAR_PRI(WEP_CRYLINK, middle_lifetime);
351 proj.fade_rate = 1 / WEP_CVAR_PRI(WEP_CRYLINK, middle_fadetime);
352 proj.nextthink = time + WEP_CVAR_PRI(WEP_CRYLINK, middle_lifetime) + WEP_CVAR_PRI(WEP_CRYLINK, middle_fadetime);
353 }
354 else
355 {
356 proj.fade_time = time + WEP_CVAR_PRI(WEP_CRYLINK, other_lifetime);
357 proj.fade_rate = 1 / WEP_CVAR_PRI(WEP_CRYLINK, other_fadetime);
358 proj.nextthink = time + WEP_CVAR_PRI(WEP_CRYLINK, other_lifetime) + WEP_CVAR_PRI(WEP_CRYLINK, other_fadetime);
359 }
360 proj.teleport_time = time + WEP_CVAR_PRI(WEP_CRYLINK, joindelay);
361 proj.cnt = WEP_CVAR_PRI(WEP_CRYLINK, bounces);
362 //proj.scale = 1 + 1 * proj.cnt;
363
364 proj.angles = vectoangles(proj.velocity);
365
366 //proj.glow_size = 20;
367
368 proj.flags = FL_PROJECTILE;
369 IL_PUSH(g_projectiles, proj);
370 IL_PUSH(g_bot_dodge, proj);
371 proj.missile_flags = MIF_SPLASH;
372
373 CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
374
375 MUTATOR_CALLHOOK(EditProjectile, actor, proj);
376 }
377 if (WEP_CVAR_PRI(WEP_CRYLINK, joinspread) != 0 && WEP_CVAR_PRI(WEP_CRYLINK, shots) > 1)
378 {
379 actor.(weaponentity).crylink_lastgroup = proj;
381 actor.(weaponentity).crylink_waitrelease = 1;
382 }
383}
IntrusiveList g_bot_dodge
Definition api.qh:150
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
vector W_CalculateSpreadPattern(int pattern, float bias, int counter, int total)
float autocvar_g_weaponspreadfactor
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
int m_id
Definition weapon.qh:43
const int FL_PROJECTILE
Definition constants.qh:77
vector v_up
float time
vector v_right
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
float speed
Definition dynlight.qc:9
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void WarpZone_RefSys_Copy(entity me, entity from)
Copies the warpzone reference of from onto me.
Definition common.qc:824
vector vectoangles(vector v)
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_BOUNCEMISSILE
Definition movetypes.qh:144
#define NULL
Definition post.qh:14
const int PROJECTILE_CRYLINK_BOUNCING
const int PROJECTILE_CRYLINK
Definition projectiles.qh:6
#define setthink(e, f)
vector
Definition self.qh:96
#define settouch(e, f)
Definition self.qh:77
const int MIF_SPLASH
Definition common.qh:58
IntrusiveList g_projectiles
Definition common.qh:70
#define PROJECTILE_MAKETRIGGER(e)
Definition common.qh:46
const int CH_WEAPON_A
Definition sound.qh:7
float ammo
Definition sv_turrets.qh:43
void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute)
Definition tracing.qc:188
vector w_shotdir
Definition tracing.qh:20
vector w_shotorg
Definition tracing.qh:19
#define W_SetupShot(ent, wepent, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition tracing.qh:34
void W_MuzzleFlash(Weapon thiswep, entity actor,.entity weaponentity, vector shotorg, vector shotdir)
Definition all.qc:715
#define WEP_CVAR_PRI(wep, name)
Definition all.qh:338
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)

References ammo, autocvar_g_weaponspreadfactor, CH_WEAPON_A, crylink_lastgroup, crylink_waitrelease, CSQCProjectile(), entity(), FL_PROJECTILE, g_bot_dodge, g_projectiles, IL_PUSH(), Weapon::m_id, MIF_SPLASH, MOVETYPE_BOUNCEMISSILE, MUTATOR_CALLHOOK, NULL, PROJECTILE_CRYLINK, PROJECTILE_CRYLINK_BOUNCING, PROJECTILE_MAKETRIGGER, set_movetype(), setthink, settouch, speed, time, v_right, v_up, vectoangles(), vector, W_CalculateSpreadPattern(), W_Crylink_CheckLinks(), W_Crylink_DeleteLink(), W_Crylink_Fadethink(), W_Crylink_Reset(), W_Crylink_Touch(), W_DecreaseAmmo(), W_MuzzleFlash(), W_SetupProjVelocity_Explicit(), W_SetupShot, w_shotdir, w_shotorg, WarpZone_RefSys_Copy(), and WEP_CVAR_PRI.

◆ W_Crylink_Attack2()

void W_Crylink_Attack2 ( Weapon thiswep,
entity actor,
.entity weaponentity )

Definition at line 385 of file crylink.qc.

386{
387 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(WEP_CRYLINK, ammo), weaponentity);
388
389 float maxdmg = WEP_CVAR_SEC(WEP_CRYLINK, damage) * WEP_CVAR_SEC(WEP_CRYLINK, shots);
390 maxdmg *= 1 + WEP_CVAR_SEC(WEP_CRYLINK, bouncedamagefactor) * WEP_CVAR_SEC(WEP_CRYLINK, bounces);
391 if (WEP_CVAR_SEC(WEP_CRYLINK, joinexplode))
392 maxdmg += WEP_CVAR_SEC(WEP_CRYLINK, joinexplode_damage);
393
394 W_SetupShot(actor, weaponentity, false, 2, SND_CRYLINK_FIRE2, CH_WEAPON_A, maxdmg, thiswep.m_id | HITTYPE_SECONDARY);
395 vector right = v_right;
396 vector up = v_up;
397
398 int shots = WEP_CVAR_SEC(WEP_CRYLINK, shots);
399 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
400 entity proj = NULL, prevproj = NULL, firstproj = NULL;
401 vector s;
402 for (int counter = 0; counter < shots; ++counter)
403 {
404 proj = new(spike);
405 WarpZone_RefSys_Copy(proj, actor);
406 proj.dtor = W_Crylink_DeleteLink;
407 proj.weaponentity_fld = weaponentity;
408 proj.reset = W_Crylink_Reset;
409 proj.realowner = proj.owner = actor;
410 proj.crylink_owner = actor;
411 proj.bot_dodge = true;
412 proj.bot_dodgerating = WEP_CVAR_SEC(WEP_CRYLINK, damage);
413 if (shots == 1)
414 {
415 proj.queuenext = proj;
416 proj.queueprev = proj;
417 }
418 else if (counter == 0) // first projectile, store in firstproj for now
419 firstproj = proj;
420 else if (counter == shots - 1) // last projectile, link up with first projectile
421 {
422 prevproj.queuenext = proj;
423 firstproj.queueprev = proj;
424 proj.queuenext = firstproj;
425 proj.queueprev = prevproj;
426 }
427 else // else link up with previous projectile
428 {
429 prevproj.queuenext = proj;
430 proj.queueprev = prevproj;
431 }
432
433 prevproj = proj;
434
437 proj.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
438 //proj.gravity = 0.001;
439
440 setorigin(proj, w_shotorg);
441 setsize(proj, '0 0 0', '0 0 0');
442
443 if (WEP_CVAR_SEC(WEP_CRYLINK, spreadtype) == 1)
444 {
445 s = W_CalculateSpreadPattern(1, 0, counter, shots) * WEP_CVAR_SEC(WEP_CRYLINK, spread) * autocvar_g_weaponspreadfactor;
446 s = w_shotdir + right * s.y + up * s.z;
447 }
448 else
449 s = w_shotdir + (((counter + 0.5) / shots) * 2 - 1) * v_right * WEP_CVAR_SEC(WEP_CRYLINK, spread) * autocvar_g_weaponspreadfactor;
450
451 W_SetupProjVelocity_Explicit(proj, s, v_up, WEP_CVAR_SEC(WEP_CRYLINK, speed), 0, 0, 0, false);
454 if (counter == (shots - 1) * 0.5)
455 {
456 proj.fade_time = time + WEP_CVAR_SEC(WEP_CRYLINK, middle_lifetime);
457 proj.fade_rate = 1 / WEP_CVAR_SEC(WEP_CRYLINK, middle_fadetime);
458 proj.nextthink = time + WEP_CVAR_SEC(WEP_CRYLINK, middle_lifetime) + WEP_CVAR_SEC(WEP_CRYLINK, middle_fadetime);
459 }
460 else
461 {
462 proj.fade_time = time + WEP_CVAR_SEC(WEP_CRYLINK, other_lifetime);
463 proj.fade_rate = 1 / WEP_CVAR_SEC(WEP_CRYLINK, other_fadetime);
464 proj.nextthink = time + WEP_CVAR_SEC(WEP_CRYLINK, other_lifetime) + WEP_CVAR_SEC(WEP_CRYLINK, other_fadetime);
465 }
466 proj.teleport_time = time + WEP_CVAR_SEC(WEP_CRYLINK, joindelay);
467 proj.cnt = WEP_CVAR_SEC(WEP_CRYLINK, bounces);
468 //proj.scale = 1 + 1 * proj.cnt;
469
470 proj.angles = vectoangles(proj.velocity);
471
472 //proj.glow_size = 20;
473
474 proj.flags = FL_PROJECTILE;
475 IL_PUSH(g_projectiles, proj);
476 IL_PUSH(g_bot_dodge, proj);
477 proj.missile_flags = MIF_SPLASH;
478
479 CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
480
481 MUTATOR_CALLHOOK(EditProjectile, actor, proj);
482 }
483 if (WEP_CVAR_SEC(WEP_CRYLINK, joinspread) != 0 && WEP_CVAR_SEC(WEP_CRYLINK, shots) > 1)
484 {
485 actor.(weaponentity).crylink_lastgroup = proj;
487 actor.(weaponentity).crylink_waitrelease = 2;
488 }
489}
const int HITTYPE_SECONDARY
Definition all.qh:31
#define WEP_CVAR_SEC(wep, name)
Definition all.qh:339

References ammo, autocvar_g_weaponspreadfactor, CH_WEAPON_A, crylink_lastgroup, crylink_waitrelease, CSQCProjectile(), entity(), FL_PROJECTILE, g_bot_dodge, g_projectiles, HITTYPE_SECONDARY, IL_PUSH(), Weapon::m_id, MIF_SPLASH, MOVETYPE_BOUNCEMISSILE, MUTATOR_CALLHOOK, NULL, PROJECTILE_CRYLINK, PROJECTILE_CRYLINK_BOUNCING, PROJECTILE_MAKETRIGGER, set_movetype(), setthink, settouch, speed, time, v_right, v_up, vectoangles(), vector, W_CalculateSpreadPattern(), W_Crylink_CheckLinks(), W_Crylink_DeleteLink(), W_Crylink_Fadethink(), W_Crylink_Reset(), W_Crylink_Touch(), W_DecreaseAmmo(), W_MuzzleFlash(), W_SetupProjVelocity_Explicit(), W_SetupShot, w_shotdir, w_shotorg, WarpZone_RefSys_Copy(), and WEP_CVAR_SEC.

◆ W_Crylink_CheckLinks()

void W_Crylink_CheckLinks ( entity e)

Definition at line 5 of file crylink.qc.

6{
7 if (e == NULL)
8 error("W_Crylink_CheckLinks: entity is NULL");
9 if (e.classname != "spike" || wasfreed(e))
10 error(sprintf("W_Crylink_CheckLinks: entity is not a spike but a %s (freed: %d)", e.classname, wasfreed(e)));
11
12 entity p = e;
13 int i;
14 for (i = 0; i < 1000; ++i)
15 {
16 if (p.queuenext.queueprev != p || p.queueprev.queuenext != p)
17 error("W_Crylink_CheckLinks: queue is inconsistent");
18 p = p.queuenext;
19 if (p == e)
20 break;
21 }
22 if (i >= 1000)
23 error("W_Crylink_CheckLinks: infinite chain");
24}
#define error
Definition pre.qh:6

References entity(), error, and NULL.

Referenced by W_Crylink_Attack(), W_Crylink_Attack2(), W_Crylink_Dequeue_Raw(), and W_Crylink_LinkJoin().

◆ W_Crylink_DeleteLink()

void W_Crylink_DeleteLink ( entity this)

Definition at line 44 of file crylink.qc.

45{
46 if (this.classname != "spike_oktoremove")
48 delete_fn(this);
49}
string classname
var void delete_fn(entity e)

References classname, delete_fn(), entity(), and W_Crylink_Dequeue().

Referenced by W_Crylink_Attack(), and W_Crylink_Attack2().

◆ W_Crylink_Dequeue()

void W_Crylink_Dequeue ( entity e)

Definition at line 39 of file crylink.qc.

40{
41 W_Crylink_Dequeue_Raw(e.crylink_owner, e.queueprev, e, e.queuenext);
42}

References entity(), and W_Crylink_Dequeue_Raw().

Referenced by W_Crylink_DeleteLink().

◆ W_Crylink_Dequeue_Raw()

void W_Crylink_Dequeue_Raw ( entity own,
entity prev,
entity me,
entity next )

Definition at line 26 of file crylink.qc.

27{
29 .entity weaponentity = me.weaponentity_fld;
30 if (me == own.(weaponentity).crylink_lastgroup)
31 own.(weaponentity).crylink_lastgroup = (me == next) ? NULL : next;
32 prev.queuenext = next;
33 next.queueprev = prev;
34 me.classname = "spike_oktoremove";
35 if (me != next)
37}
prev
Definition all.qh:53
next
Definition all.qh:75

References crylink_lastgroup, entity(), next, NULL, prev, and W_Crylink_CheckLinks().

Referenced by W_Crylink_Dequeue().

◆ W_Crylink_Fadethink()

void W_Crylink_Fadethink ( entity this)

Definition at line 280 of file crylink.qc.

281{
282 delete(this);
283}

References entity().

Referenced by W_Crylink_Attack(), and W_Crylink_Attack2().

◆ W_Crylink_LinkExplode()

void W_Crylink_LinkExplode ( entity e,
entity e2,
entity directhitentity )

Definition at line 57 of file crylink.qc.

58{
59 if (e == e2)
60 return;
61
62 float a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1);
63
64 .entity weaponentity = e.weaponentity_fld;
65 if (e == e.crylink_owner.(weaponentity).crylink_lastgroup)
66 e.crylink_owner.(weaponentity).crylink_lastgroup = NULL;
67
68 bool is_primary = !(e.projectiledeathtype & HITTYPE_SECONDARY);
69 RadiusDamage(e, e.realowner,
70 a * WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, damage),
71 a * WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, edgedamage),
72 WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, radius),
73 NULL,
74 NULL,
75 a * WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, force),
76 e.projectiledeathtype,
77 e.weaponentity_fld,
78 directhitentity
79 );
80
81 W_Crylink_LinkExplode(e.queuenext, e2, directhitentity);
82
83 e.classname = "spike_oktoremove";
84 delete(e);
85}
float radius
Definition impulse.qh:11
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:937
float bound(float min, float value, float max)
#define WEP_CVAR_BOTH(wep, isprimary, name)
Definition all.qh:340

References bound(), crylink_lastgroup, entity(), HITTYPE_SECONDARY, NULL, radius, RadiusDamage(), time, W_Crylink_LinkExplode(), and WEP_CVAR_BOTH.

Referenced by W_Crylink_LinkExplode(), and W_Crylink_Touch().

◆ W_Crylink_LinkJoin()

vector W_Crylink_LinkJoin ( entity e,
float jspeed )

Definition at line 94 of file crylink.qc.

95{
96 // FIXME remove this debug code
98
100
101 entity p;
102 vector avg_org = e.origin;
103 vector avg_vel = e.velocity;
104 float n = 1;
105 for (p = e; (p = p.queuenext) != e; )
106 {
107 avg_org += WarpZone_RefSys_TransformOrigin(p, e, p.origin);
108 avg_vel += WarpZone_RefSys_TransformVelocity(p, e, p.velocity);
109 ++n;
110 }
111 avg_org *= 1.0 / n;
112 avg_vel *= 1.0 / n;
113
114 if (n < 2)
115 return avg_org; // nothing to do
116
117 // yes, mathematically we can do this in ONE step, but beware of 32bit floats...
118 float avg_dist = vlen2(e.origin - avg_org);
119 for (p = e; (p = p.queuenext) != e; )
120 avg_dist += vlen2(WarpZone_RefSys_TransformOrigin(p, e, p.origin) - avg_org);
121 avg_dist = sqrt(avg_dist * (1.0 / n));
122
123 if (avg_dist == 0)
124 return avg_org; // no change needed
125
126 vector targ_origin;
127 if (jspeed == 0)
128 {
129 e.velocity = avg_vel;
131 for (p = e; (p = p.queuenext) != e; )
132 {
133 p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_vel);
135 }
136 targ_origin = avg_org + 1000000000 * normalize(avg_vel); // HUUUUUUGE
137 }
138 else
139 {
140 w_crylink_linkjoin_time = avg_dist / jspeed;
141 targ_origin = avg_org + w_crylink_linkjoin_time * avg_vel;
142
143 e.velocity = (targ_origin - e.origin) * (1.0 / w_crylink_linkjoin_time);
145 for (p = e; (p = p.queuenext) != e; )
146 {
147 p.velocity = WarpZone_RefSys_TransformVelocity(e, p, (targ_origin - WarpZone_RefSys_TransformOrigin(p, e, p.origin)) * (1.0 / w_crylink_linkjoin_time));
149 }
150
151 // analysis:
152 // jspeed -> +infinity:
153 // w_crylink_linkjoin_time -> +0
154 // targ_origin -> avg_org
155 // p->velocity -> HUEG towards center
156 // jspeed -> 0:
157 // w_crylink_linkjoin_time -> +/- infinity
158 // targ_origin -> avg_vel * +/- infinity
159 // p->velocity -> avg_vel
160 // jspeed -> -infinity:
161 // w_crylink_linkjoin_time -> -0
162 // targ_origin -> avg_org
163 // p->velocity -> HUEG away from center
164 }
165
167
168 return targ_origin;
169}
void UpdateCSQCProjectile(entity e)
vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel)
Transform velocity vel in from's reference into to's reference.
Definition common.qc:796
vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
Transform origin org in from's reference into to's reference.
Definition common.qc:787
float sqrt(float f)
vector normalize(vector v)
#define vlen2(v)
Definition vector.qh:4

References entity(), normalize(), sqrt(), UpdateCSQCProjectile(), vector, vlen2, W_Crylink_CheckLinks(), w_crylink_linkjoin_time, WarpZone_RefSys_TransformOrigin(), and WarpZone_RefSys_TransformVelocity().

◆ W_Crylink_LinkJoinEffect_Think()

void W_Crylink_LinkJoinEffect_Think ( entity this)

Definition at line 171 of file crylink.qc.

172{
173 // is there at least 2 projectiles very close?
174 .entity weaponentity = this.weaponentity_fld;
175 entity e = this.owner.(weaponentity).crylink_lastgroup;
176 if (e)
177 {
178 float n = 0;
179 if (vlen2(e.origin - this.origin) < vlen2(e.velocity) * frametime)
180 ++n;
181 for (entity p = e; (p = p.queuenext) != e; )
182 if (vlen2(p.origin - this.origin) < vlen2(p.velocity) * frametime)
183 ++n;
184 if (n >= 2)
185 {
186 bool is_primary = !(e.projectiledeathtype & HITTYPE_SECONDARY);
187
188 if (WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, joinexplode))
189 {
190 n /= WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, shots);
191 RadiusDamage(e, e.realowner,
192 n * WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, joinexplode_damage),
193 n * WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, joinexplode_edgedamage),
194 n * WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, joinexplode_radius),
195 e.realowner,
196 NULL,
197 n * WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, joinexplode_force),
198 e.projectiledeathtype,
199 e.weaponentity_fld,
200 NULL
201 );
202 Send_Effect(EFFECT_CRYLINK_JOINEXPLODE, this.origin, '0 0 0', n);
203 }
204 }
205 }
206 delete(this);
207}
entity owner
Definition main.qh:87
float frametime
vector origin
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:155
entity weaponentity_fld

References crylink_lastgroup, entity(), frametime, HITTYPE_SECONDARY, NULL, origin, owner, RadiusDamage(), Send_Effect(), vlen2, weaponentity_fld, and WEP_CVAR_BOTH.

◆ W_Crylink_Reset()

void W_Crylink_Reset ( entity this)

Definition at line 51 of file crylink.qc.

52{
53 delete(this);
54}

References entity().

Referenced by W_Crylink_Attack(), and W_Crylink_Attack2().

◆ W_Crylink_Touch()

void W_Crylink_Touch ( entity this,
entity toucher )

Definition at line 230 of file crylink.qc.

231{
232 bool is_primary = !(this.projectiledeathtype & HITTYPE_SECONDARY);
234
235 float a = bound(0, 1 - (time - this.fade_time) * this.fade_rate, 1);
236 float finalhit = (this.cnt <= 0 || toucher.takedamage != DAMAGE_NO);
237 float f = (finalhit ? 1 : WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, bouncedamagefactor));
238 if (a)
239 f *= a;
240
241 float totaldamage = RadiusDamage(this, this.realowner,
242 f * WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, damage),
243 f * WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, edgedamage),
244 WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, radius),
245 NULL,
246 NULL,
247 f * WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, force),
249 this.weaponentity_fld,
250 toucher
251 );
252
253 if (totaldamage
254 && ((WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, linkexplode) == 1 && !W_Crylink_Touch_WouldHitFriendly(this, WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, radius)))
255 || WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, linkexplode) == 2))
256 {
257 .entity weaponentity = this.weaponentity_fld;
258 if (this == this.crylink_owner.(weaponentity).crylink_lastgroup)
259 this.crylink_owner.(weaponentity).crylink_lastgroup = NULL;
261 this.classname = "spike_oktoremove";
262 delete(this);
263 return;
264 }
265 else if (finalhit)
266 {
267 // just unlink
268 delete(this);
269 return;
270 }
271 --this.cnt;
272 this.angles = vectoangles(this.velocity);
273 this.owner = NULL;
275 // commented out as it causes a little hitch...
276 //if (proj.cnt == 0)
277 // CSQCProjectile(proj, true, PROJECTILE_CRYLINK, true);
278}
float cnt
Definition powerups.qc:24
vector velocity
const int HITTYPE_BOUNCE
set manually after projectile has bounced
Definition all.qh:33
ent angles
Definition ent_cs.qc:146
fade_rate
Definition projectile.qh:14
entity entity toucher
Definition self.qh:76
int projectiledeathtype
Definition common.qh:33
#define PROJECTILE_TOUCH(e, t)
Definition common.qh:40
float fade_time
Definition common.qh:35
const int DAMAGE_NO
Definition subs.qh:79
entity realowner

References angles, bound(), classname, cnt, crylink_lastgroup, crylink_owner, DAMAGE_NO, entity(), fade_rate, fade_time, HITTYPE_BOUNCE, HITTYPE_SECONDARY, NULL, owner, PROJECTILE_TOUCH, projectiledeathtype, queuenext, radius, RadiusDamage(), realowner, time, toucher, vectoangles(), velocity, W_Crylink_LinkExplode(), W_Crylink_Touch_WouldHitFriendly(), weaponentity_fld, and WEP_CVAR_BOTH.

Referenced by W_Crylink_Attack(), and W_Crylink_Attack2().

◆ W_Crylink_Touch_WouldHitFriendly()

bool W_Crylink_Touch_WouldHitFriendly ( entity projectile,
float rad )

Definition at line 213 of file crylink.qc.

214{
215 entity head = WarpZone_SearchInRadius(projectile.origin + (projectile.mins + projectile.maxs) * 0.5, rad + MAX_DAMAGEEXTRARADIUS,
217 bool hit_friendly = false;
218 for (; head; head = head.chain)
219 {
220 if (SAME_TEAM(head, projectile.realowner))
221 hit_friendly = true;
222 else
223 return false;
224 }
225
226 return hit_friendly;
227}
const float MAX_DAMAGEEXTRARADIUS
entity WarpZone_SearchInRadius(vector org, float rad, float nomonsters, WarpZone_FindRadius_cond_callback_t cb)
Modified findradius aware of warpzones, that only includes entities that meet the "cb" criteria.
Definition common.qc:680
#define MOVE_NOTHING
Definition common.qh:35
#define SAME_TEAM(a, b)
Definition teams.qh:241

References entity(), MAX_DAMAGEEXTRARADIUS, MOVE_NOTHING, SAME_TEAM, W_Crylink_Touch_WouldHitFriendly_cond(), and WarpZone_SearchInRadius().

Referenced by W_Crylink_Touch().

◆ W_Crylink_Touch_WouldHitFriendly_cond()

bool W_Crylink_Touch_WouldHitFriendly_cond ( entity e)

Definition at line 209 of file crylink.qc.

210{
211 return (e.takedamage != DAMAGE_NO && !IS_DEAD(e));
212}
#define IS_DEAD(s)
Definition player.qh:244

References DAMAGE_NO, entity(), and IS_DEAD.

Referenced by W_Crylink_Touch_WouldHitFriendly().

Variable Documentation

◆ w_crylink_linkjoin_time

float w_crylink_linkjoin_time

Definition at line 93 of file crylink.qc.

Referenced by W_Crylink_LinkJoin().