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)));
14 for (i = 0; i < 1000; ++i)
16 if (p.queuenext.queueprev != p || p.queueprev.queuenext != p)
17 error(
"W_Crylink_CheckLinks: queue is inconsistent");
23 error(
"W_Crylink_CheckLinks: infinite chain");
29 .entity weaponentity = me.weaponentity_fld;
30 if (me == own.(weaponentity).crylink_lastgroup)
34 me.classname =
"spike_oktoremove";
62 float a =
bound(0, 1 - (
time - e.fade_time) * e.fade_rate, 1);
64 .entity weaponentity = e.weaponentity_fld;
65 if (e == e.crylink_owner.(weaponentity).crylink_lastgroup)
76 e.projectiledeathtype,
83 e.classname =
"spike_oktoremove";
102 vector avg_org = e.origin;
103 vector avg_vel = e.velocity;
105 for (p = e; (p = p.queuenext) != e; )
118 float avg_dist =
vlen2(e.origin - avg_org);
119 for (p = e; (p = p.queuenext) != e; )
121 avg_dist =
sqrt(avg_dist * (1.0 / n));
129 e.velocity = avg_vel;
131 for (p = e; (p = p.queuenext) != e; )
136 targ_origin = avg_org + 1000000000 *
normalize(avg_vel);
145 for (p = e; (p = p.queuenext) != e; )
181 for (
entity p = e; (p = p.queuenext) != e; )
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),
197 n *
WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, joinexplode_force),
198 e.projectiledeathtype,
212 bool hit_friendly =
false;
213 for (; head; head = head.chain)
216 if (
SAME_TEAM(head, projectile.realowner))
233 float f = (finalhit ? 1 :
WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, bouncedamagefactor));
251 ||
WEP_CVAR_BOTH(WEP_CRYLINK, is_primary, linkexplode) == 2))
254 if (
this == this.
crylink_owner.(weaponentity).crylink_lastgroup)
288 maxdmg +=
WEP_CVAR_PRI(WEP_CRYLINK, joinexplode_damage);
298 for (
int counter = 0; counter < shots; ++counter)
303 proj.realowner = proj.owner = actor;
304 proj.crylink_owner = actor;
305 proj.weaponentity_fld = weaponentity;
306 proj.bot_dodge =
true;
307 proj.bot_dodgerating =
WEP_CVAR_PRI(WEP_CRYLINK, damage);
310 proj.queuenext = proj;
311 proj.queueprev = proj;
313 else if (counter == 0)
315 else if (counter == shots - 1)
317 prevproj.queuenext = proj;
318 firstproj.queueprev = proj;
319 proj.queuenext = firstproj;
320 proj.queueprev = prevproj;
324 prevproj.queuenext = proj;
325 proj.queueprev = prevproj;
332 proj.projectiledeathtype = thiswep.
m_id;
336 setsize(proj,
'0 0 0',
'0 0 0');
346 proj.fade_rate = 1 /
WEP_CVAR_PRI(WEP_CRYLINK, middle_fadetime);
352 proj.fade_rate = 1 /
WEP_CVAR_PRI(WEP_CRYLINK, other_fadetime);
387 maxdmg +=
WEP_CVAR_SEC(WEP_CRYLINK, joinexplode_damage);
397 for (
int counter = 0; counter < shots; ++counter)
401 proj.weaponentity_fld = weaponentity;
403 proj.realowner = proj.owner = actor;
404 proj.crylink_owner = actor;
405 proj.bot_dodge =
true;
406 proj.bot_dodgerating =
WEP_CVAR_SEC(WEP_CRYLINK, damage);
409 proj.queuenext = proj;
410 proj.queueprev = proj;
412 else if (counter == 0)
414 else if (counter == shots - 1)
416 prevproj.queuenext = proj;
417 firstproj.queueprev = proj;
418 proj.queuenext = firstproj;
419 proj.queueprev = prevproj;
423 prevproj.queuenext = proj;
424 proj.queueprev = prevproj;
435 setsize(proj,
'0 0 0',
'0 0 0');
448 if (counter == (shots - 1) * 0.5)
451 proj.fade_rate = 1 /
WEP_CVAR_SEC(WEP_CRYLINK, middle_fadetime);
457 proj.fade_rate = 1 /
WEP_CVAR_SEC(WEP_CRYLINK, other_fadetime);
495 if (autocvar_g_balance_crylink_reload_ammo
498 thiswep.wr_reload(thiswep, actor, weaponentity);
501 if (actor.(weaponentity).crylink_waitrelease != 1
508 else if ((fire & 2) && autocvar_g_balance_crylink_secondary)
510 if (actor.(weaponentity).crylink_waitrelease != 2
518 if ((actor.(weaponentity).crylink_waitrelease == 1 && !(fire & 1))
519 || (actor.(weaponentity).crylink_waitrelease == 2 && !(fire & 2)))
521 if (!actor.(weaponentity).crylink_lastgroup ||
time > actor.(weaponentity).crylink_lastgroup.teleport_time)
524 if (actor.(weaponentity).crylink_lastgroup)
526 bool is_primary = (actor.(weaponentity).crylink_waitrelease == 1);
529 entity linkjoineffect =
new(linkjoineffect);
530 linkjoineffect.weaponentity_fld = weaponentity;
533 linkjoineffect.owner = actor;
534 setorigin(linkjoineffect, pos);
537 if (!thiswep.wr_checkammo1(thiswep, actor, weaponentity) && !thiswep.wr_checkammo2(thiswep, actor, weaponentity)
541 actor.cnt = thiswep.m_id;
551 if (actor.(weaponentity).crylink_lastgroup && actor.(weaponentity).crylink_waitrelease)
562 if (actor.(weaponentity).crylink_lastgroup && actor.(weaponentity).crylink_waitrelease)
577 return WEAPON_CRYLINK_SUICIDE;
582 return WEAPON_CRYLINK_MURDER;
613 PAR(_(
"The %s fires bursts of laser-like projectiles, spreading out as they travel away and deflecting off walls. "
614 "If the primary fire is held, when it's released the projectiles will converge before spreading out again, "
615 "which can be utilized to deal more damage to an enemy by making the projectiles converge on them."),
COLORED_NAME(
this));
616 PAR(_(
"Projectiles deal damage on collision but also when they bounce, so with good positioning they can sometimes deal double damage."));
617 PAR(_(
"The secondary fire shoots the projectiles together in a tight group, so it is often the better option in situations where the enemy is an easy target to hit."));
618 PAR(_(
"It consumes %s ammo for each projectile, which is shared by several weapons."),
COLORED_NAME(ITEM_Cells));
619 PAR(_(
"Close to medium range is the ideal time to use the %s, although the secondary fire can be useful for long range combat sometimes."),
COLORED_NAME(
this));
620 PAR(_(
"The %s deals knockback in a unique way, pulling the player from their center to the point of impact. "
621 "This makes it one of the best weapons to slow someone down if you are chasing them, particularly with the secondary fire. "
622 "Another common use of the %s is \"crylink running,\" where you partially angle down and use the secondary fire to pull yourself forwards, in order to gain speed."),
COLORED_NAME(
this),
COLORED_NAME(
this));
bool bot_aim(entity this,.entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity, bool shot_accurate)
IntrusiveList g_bot_dodge
#define MUTATOR_CALLHOOK(id,...)
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
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
#define COLORED_NAME(this)
const int IT_UNLIMITED_AMMO
#define PHYS_INPUT_BUTTON_ATCK(s)
#define PHYS_INPUT_BUTTON_ATCK2(s)
void W_Crylink_Reset(entity this)
void W_Crylink_Touch(entity this, entity toucher)
void W_Crylink_Dequeue_Raw(entity own, entity prev, entity me, entity next)
void W_Crylink_LinkExplode(entity e, entity e2, entity directhitentity)
bool W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad)
void W_Crylink_DeleteLink(entity this)
void W_Crylink_Attack2(Weapon thiswep, entity actor,.entity weaponentity)
float w_crylink_linkjoin_time
void W_Crylink_Attack(Weapon thiswep, entity actor,.entity weaponentity)
vector W_Crylink_LinkJoin(entity e, float jspeed)
void W_Crylink_CheckLinks(entity e)
void W_Crylink_LinkJoinEffect_Think(entity this)
void W_Crylink_Fadethink(entity this)
void W_Crylink_Dequeue(entity e)
float crylink_waitrelease
void UpdateCSQCProjectile(entity e)
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)
const float MAX_DAMAGEEXTRARADIUS
const int HITTYPE_SECONDARY
#define pointparticles(effect, org, vel, howmany)
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
vector WarpZone_RefSys_TransformVelocity(entity from, entity to, vector vel)
entity WarpZone_FindRadius(vector org, float rad, bool needlineofsight)
vector WarpZone_RefSys_TransformOrigin(entity from, entity to, vector org)
void set_movetype(entity this, int mt)
const int MOVETYPE_BOUNCEMISSILE
entity Notification
always last
#define METHOD(cname, name, prototype)
const int PROJECTILE_CRYLINK_BOUNCING
const int PROJECTILE_CRYLINK
#define w_getbestweapon(ent, wepent)
#define PROJECTILE_TOUCH(e, t)
IntrusiveList g_projectiles
#define PROJECTILE_MAKETRIGGER(e)
#define sound(e, c, s, v, a)
#define PAR(...)
Adds an individually translatable paragraph to PAGE_TEXT without having to deal with strcat and sprin...
var void delete_fn(entity e)
void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute)
#define W_SetupShot(ent, wepent, antilag, recoil, snd, chan, maxdamage, deathtype)
string W_Guide_Keybinds(Weapon wep)
string W_Guide_DPS_bothMultishot(string name, string pri, string sec)
void W_MuzzleFlash(Weapon thiswep, entity actor,.entity weaponentity, vector shotorg, vector shotdir)
#define WEP_CVAR_PRI(wep, name)
#define WEP_CVAR_BOTH(wep, isprimary, name)
#define WEP_CVAR_SEC(wep, name)
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)
void W_Reload(entity actor,.entity weaponentity, float sent_ammo_min, Sound sent_sound)
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
bool weapon_prepareattack(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
float weapon_load[REGISTRY_MAX(Weapons)]