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)
float W_Crylink_Touch_WouldHitFriendly (entity projectile, float rad)

Variables

float w_crylink_linkjoin_time

Function Documentation

◆ W_Crylink_Attack()

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

Definition at line 289 of file crylink.qc.

290{
291 float counter, shots;
292 entity proj, prevproj, firstproj;
293 vector s;
294 vector forward, right, up;
295 float maxdmg;
296
297 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(WEP_CRYLINK, ammo), weaponentity);
298
299 maxdmg = WEP_CVAR_PRI(WEP_CRYLINK, damage) * WEP_CVAR_PRI(WEP_CRYLINK, shots);
300 maxdmg *= 1 + WEP_CVAR_PRI(WEP_CRYLINK, bouncedamagefactor) * WEP_CVAR_PRI(WEP_CRYLINK, bounces);
301 if(WEP_CVAR_PRI(WEP_CRYLINK, joinexplode))
302 maxdmg += WEP_CVAR_PRI(WEP_CRYLINK, joinexplode_damage);
303
304 W_SetupShot(actor, weaponentity, false, 2, SND_CRYLINK_FIRE, CH_WEAPON_A, maxdmg, thiswep.m_id);
305 forward = v_forward;
306 right = v_right;
307 up = v_up;
308
309 shots = WEP_CVAR_PRI(WEP_CRYLINK, shots);
310 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
311 proj = prevproj = firstproj = NULL;
312 for(counter = 0; counter < shots; ++counter)
313 {
314 proj = new(spike);
315 proj.dtor = W_Crylink_DeleteLink;
316 proj.reset = W_Crylink_Reset;
317 proj.realowner = proj.owner = actor;
318 proj.crylink_owner = actor;
319 proj.weaponentity_fld = weaponentity;
320 proj.bot_dodge = true;
321 proj.bot_dodgerating = WEP_CVAR_PRI(WEP_CRYLINK, damage);
322 if(shots == 1) {
323 proj.queuenext = proj;
324 proj.queueprev = proj;
325 }
326 else if(counter == 0) { // first projectile, store in firstproj for now
327 firstproj = proj;
328 }
329 else if(counter == shots - 1) { // last projectile, link up with first projectile
330 prevproj.queuenext = proj;
331 firstproj.queueprev = proj;
332 proj.queuenext = firstproj;
333 proj.queueprev = prevproj;
334 }
335 else { // else link up with previous projectile
336 prevproj.queuenext = proj;
337 proj.queueprev = prevproj;
338 }
339
340 prevproj = proj;
341
344 proj.projectiledeathtype = thiswep.m_id;
345 //proj.gravity = 0.001;
346
347 setorigin(proj, w_shotorg);
348 setsize(proj, '0 0 0', '0 0 0');
349
350 s = W_CalculateSpreadPattern(1, 0, counter, shots);
351 s = s * WEP_CVAR_PRI(WEP_CRYLINK, spread) * autocvar_g_weaponspreadfactor;
352 W_SetupProjVelocity_Explicit(proj, w_shotdir + right * s.y + up * s.z, v_up, WEP_CVAR_PRI(WEP_CRYLINK, speed), 0, 0, 0, false);
354
356 if(counter == 0)
357 {
358 proj.fade_time = time + WEP_CVAR_PRI(WEP_CRYLINK, middle_lifetime);
359 proj.fade_rate = 1 / WEP_CVAR_PRI(WEP_CRYLINK, middle_fadetime);
360 proj.nextthink = time + WEP_CVAR_PRI(WEP_CRYLINK, middle_lifetime) + WEP_CVAR_PRI(WEP_CRYLINK, middle_fadetime);
361 }
362 else
363 {
364 proj.fade_time = time + WEP_CVAR_PRI(WEP_CRYLINK, other_lifetime);
365 proj.fade_rate = 1 / WEP_CVAR_PRI(WEP_CRYLINK, other_fadetime);
366 proj.nextthink = time + WEP_CVAR_PRI(WEP_CRYLINK, other_lifetime) + WEP_CVAR_PRI(WEP_CRYLINK, other_fadetime);
367 }
368 proj.teleport_time = time + WEP_CVAR_PRI(WEP_CRYLINK, joindelay);
369 proj.cnt = WEP_CVAR_PRI(WEP_CRYLINK, bounces);
370 //proj.scale = 1 + 1 * proj.cnt;
371
372 proj.angles = vectoangles(proj.velocity);
373
374 //proj.glow_size = 20;
375
376 proj.flags = FL_PROJECTILE;
377 IL_PUSH(g_projectiles, proj);
378 IL_PUSH(g_bot_dodge, proj);
379 proj.missile_flags = MIF_SPLASH;
380
381 CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
382
383 MUTATOR_CALLHOOK(EditProjectile, actor, proj);
384 }
385 if(WEP_CVAR_PRI(WEP_CRYLINK, joinspread) != 0 && WEP_CVAR_PRI(WEP_CRYLINK, shots) > 1)
386 {
387 actor.(weaponentity).crylink_lastgroup = proj;
389 actor.(weaponentity).crylink_waitrelease = 1;
390 }
391}
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:45
const int FL_PROJECTILE
Definition constants.qh:85
vector v_up
float time
vector v_right
vector v_forward
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.
vector vectoangles(vector v)
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_BOUNCEMISSILE
Definition movetypes.qh:140
#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:92
#define settouch(e, f)
Definition self.qh:73
const int MIF_SPLASH
Definition common.qh:46
IntrusiveList g_projectiles
Definition common.qh:58
#define PROJECTILE_MAKETRIGGER(e)
Definition common.qh:34
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:192
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:728
#define WEP_CVAR_PRI(wep, name)
Definition all.qh:322
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_forward, 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, and WEP_CVAR_PRI.

◆ W_Crylink_Attack2()

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

Definition at line 393 of file crylink.qc.

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

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_forward, 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, and WEP_CVAR_SEC.

◆ W_Crylink_CheckLinks()

void W_Crylink_CheckLinks ( entity e)

Definition at line 5 of file crylink.qc.

6{
7 float i;
8 entity p;
9
10 if(e == NULL)
11 error("W_Crylink_CheckLinks: entity is NULL");
12 if(e.classname != "spike" || wasfreed(e))
13 error(sprintf("W_Crylink_CheckLinks: entity is not a spike but a %s (freed: %d)", e.classname, wasfreed(e)));
14
15 p = e;
16 for(i = 0; i < 1000; ++i)
17 {
18 if(p.queuenext.queueprev != p || p.queueprev.queuenext != p)
19 error("W_Crylink_CheckLinks: queue is inconsistent");
20 p = p.queuenext;
21 if(p == e)
22 break;
23 }
24 if(i >= 1000)
25 error("W_Crylink_CheckLinks: infinite chain");
26}
#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 46 of file crylink.qc.

47{
48 if(this.classname != "spike_oktoremove")
50 delete_fn(this);
51}
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 41 of file crylink.qc.

42{
43 W_Crylink_Dequeue_Raw(e.crylink_owner, e.queueprev, e, e.queuenext);
44}

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 28 of file crylink.qc.

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

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 284 of file crylink.qc.

285{
286 delete(this);
287}

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 59 of file crylink.qc.

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

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 90 of file crylink.qc.

91{
92 vector avg_origin, avg_velocity;
93 vector targ_origin;
94 float avg_dist, n;
95 entity p;
96
97 // FIXME remove this debug code
99
101
102 avg_origin = e.origin;
103 avg_velocity = e.velocity;
104 n = 1;
105 for(p = e; (p = p.queuenext) != e; )
106 {
107 avg_origin += WarpZone_RefSys_TransformOrigin(p, e, p.origin);
108 avg_velocity += WarpZone_RefSys_TransformVelocity(p, e, p.velocity);
109 ++n;
110 }
111 avg_origin *= (1.0 / n);
112 avg_velocity *= (1.0 / n);
113
114 if(n < 2)
115 return avg_origin; // nothing to do
116
117 // yes, mathematically we can do this in ONE step, but beware of 32bit floats...
118 avg_dist = (vlen(e.origin - avg_origin) ** 2);
119 for(p = e; (p = p.queuenext) != e; )
120 avg_dist += (vlen(WarpZone_RefSys_TransformOrigin(p, e, p.origin) - avg_origin) ** 2);
121 avg_dist *= (1.0 / n);
122 avg_dist = sqrt(avg_dist);
123
124 if(avg_dist == 0)
125 return avg_origin; // no change needed
126
127 if(jspeed == 0)
128 {
129 e.velocity = avg_velocity;
131 for(p = e; (p = p.queuenext) != e; )
132 {
133 p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_velocity);
135 }
136 targ_origin = avg_origin + 1000000000 * normalize(avg_velocity); // HUUUUUUGE
137 }
138 else
139 {
140 w_crylink_linkjoin_time = avg_dist / jspeed;
141 targ_origin = avg_origin + w_crylink_linkjoin_time * avg_velocity;
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_origin
155 // p->velocity -> HUEG towards center
156 // jspeed -> 0:
157 // w_crylink_linkjoin_time -> +/- infinity
158 // targ_origin -> avg_velocity * +/- infinity
159 // p->velocity -> avg_velocity
160 // jspeed -> -infinity:
161 // w_crylink_linkjoin_time -> -0
162 // targ_origin -> avg_origin
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)
Definition common.qc:773
vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
Definition common.qc:765
float vlen(vector v)
float sqrt(float f)
vector normalize(vector v)

References entity(), normalize(), sqrt(), UpdateCSQCProjectile(), vector, vlen(), 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 e, p;
175 float n;
176 .entity weaponentity = this.weaponentity_fld;
177 e = this.owner.(weaponentity).crylink_lastgroup;
178 n = 0;
179 if(e)
180 {
181 if(vlen2(e.origin - this.origin) < vlen2(e.velocity) * frametime)
182 ++n;
183 for(p = e; (p = p.queuenext) != e; )
184 {
185 if(vlen2(p.origin - this.origin) < vlen2(p.velocity) * frametime)
186 ++n;
187 }
188 if(n >= 2)
189 {
190 float isprimary = !(e.projectiledeathtype & HITTYPE_SECONDARY);
191
192 if(WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, joinexplode))
193 {
194 n /= WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, shots);
196 e,
197 e.realowner,
198 WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, joinexplode_damage) * n,
199 WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, joinexplode_edgedamage) * n,
200 WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, joinexplode_radius) * n,
201 e.realowner,
202 NULL,
203 WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, joinexplode_force) * n,
204 e.projectiledeathtype,
205 e.weaponentity_fld,
206 NULL
207 );
208 Send_Effect(EFFECT_CRYLINK_JOINEXPLODE, this.origin, '0 0 0', n);
209 }
210 }
211 }
212 delete(this);
213}
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:124
#define vlen2(v)
Definition vector.qh:4
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 53 of file crylink.qc.

54{
55 delete(this);
56}

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 238 of file crylink.qc.

239{
240 float finalhit;
241 float f;
242 float isprimary = !(this.projectiledeathtype & HITTYPE_SECONDARY);
244
245 float a;
246 a = bound(0, 1 - (time - this.fade_time) * this.fade_rate, 1);
247
248 finalhit = ((this.cnt <= 0) || (toucher.takedamage != DAMAGE_NO));
249 if(finalhit)
250 f = 1;
251 else
252 f = WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, bouncedamagefactor);
253 if(a)
254 f *= a;
255
256 float totaldamage = RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, damage) * f, WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, edgedamage) * f, WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, radius),
257 NULL, NULL, WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, force) * f, this.projectiledeathtype, this.weaponentity_fld, toucher);
258
259 if(totaldamage && ((WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, linkexplode) == 2) || ((WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, linkexplode) == 1) && !W_Crylink_Touch_WouldHitFriendly(this, WEP_CVAR_BOTH(WEP_CRYLINK, isprimary, radius)))))
260 {
261 .entity weaponentity = this.weaponentity_fld;
262 if(this == this.crylink_owner.(weaponentity).crylink_lastgroup)
263 this.crylink_owner.(weaponentity).crylink_lastgroup = NULL;
265 this.classname = "spike_oktoremove";
266 delete(this);
267 return;
268 }
269 else if(finalhit)
270 {
271 // just unlink
272 delete(this);
273 return;
274 }
275 this.cnt = this.cnt - 1;
276 this.angles = vectoangles(this.velocity);
277 this.owner = NULL;
279 // commented out as it causes a little hitch...
280 //if(proj.cnt == 0)
281 // CSQCProjectile(proj, true, PROJECTILE_CRYLINK, true);
282}
float cnt
Definition powerups.qc:24
vector velocity
const int HITTYPE_BOUNCE
Definition all.qh:31
ent angles
Definition ent_cs.qc:121
fade_rate
Definition projectile.qh:14
entity entity toucher
Definition self.qh:72
int projectiledeathtype
Definition common.qh:21
#define PROJECTILE_TOUCH(e, t)
Definition common.qh:28
float fade_time
Definition common.qh:23
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()

float W_Crylink_Touch_WouldHitFriendly ( entity projectile,
float rad )

Definition at line 215 of file crylink.qc.

216{
217 entity head = WarpZone_FindRadius((projectile.origin + (projectile.mins + projectile.maxs) * 0.5), rad + MAX_DAMAGEEXTRARADIUS, false);
218 float hit_friendly = 0;
219 float hit_enemy = 0;
220
221 while(head)
222 {
223 if((head.takedamage != DAMAGE_NO) && (!IS_DEAD(head)))
224 {
225 if(SAME_TEAM(head, projectile.realowner))
226 ++hit_friendly;
227 else
228 ++hit_enemy;
229 }
230
231 head = head.chain;
232 }
233
234 return (hit_enemy ? false : hit_friendly);
235}
#define IS_DEAD(s)
Definition player.qh:245
const float MAX_DAMAGEEXTRARADIUS
entity WarpZone_FindRadius(vector org, float rad, bool needlineofsight)
Definition common.qc:686
#define SAME_TEAM(a, b)
Definition teams.qh:241

References DAMAGE_NO, entity(), IS_DEAD, MAX_DAMAGEEXTRARADIUS, SAME_TEAM, and WarpZone_FindRadius().

Referenced by W_Crylink_Touch().

Variable Documentation

◆ w_crylink_linkjoin_time

float w_crylink_linkjoin_time

Definition at line 89 of file crylink.qc.

Referenced by W_Crylink_LinkJoin().