/* wepimg */ ATTRIB(Crylink, model2, string, "weaponcrylink");
/* refname */ ATTRIB(Crylink, netname, string, "crylink");
/* wepname */ ATTRIB(Crylink, m_name, string, _("Crylink"));
+
+#define X(BEGIN, P, END, class, prefix) \
+ BEGIN(class) \
+ P(class, prefix, ammo, float, BOTH) \
+ P(class, prefix, animtime, float, BOTH) \
+ P(class, prefix, bouncedamagefactor, float, BOTH) \
+ P(class, prefix, bounces, float, BOTH) \
+ P(class, prefix, damage, float, BOTH) \
+ P(class, prefix, edgedamage, float, BOTH) \
+ P(class, prefix, force, float, BOTH) \
+ P(class, prefix, joindelay, float, BOTH) \
+ P(class, prefix, joinexplode, float, BOTH) \
+ P(class, prefix, joinexplode_damage, float, BOTH) \
+ P(class, prefix, joinexplode_edgedamage, float, BOTH) \
+ P(class, prefix, joinexplode_force, float, BOTH) \
+ P(class, prefix, joinexplode_radius, float, BOTH) \
+ P(class, prefix, joinspread, float, BOTH) \
+ P(class, prefix, linkexplode, float, BOTH) \
+ P(class, prefix, middle_fadetime, float, BOTH) \
+ P(class, prefix, middle_lifetime, float, BOTH) \
+ P(class, prefix, other_fadetime, float, BOTH) \
+ P(class, prefix, other_lifetime, float, BOTH) \
+ P(class, prefix, radius, float, BOTH) \
+ P(class, prefix, refire, float, BOTH) \
+ P(class, prefix, reload_ammo, float, NONE) \
+ P(class, prefix, reload_time, float, NONE) \
+ P(class, prefix, secondary, float, NONE) \
+ P(class, prefix, shots, float, BOTH) \
+ P(class, prefix, speed, float, BOTH) \
+ P(class, prefix, spreadtype, float, SEC) \
+ P(class, prefix, spread, float, BOTH) \
+ P(class, prefix, switchdelay_drop, float, NONE) \
+ P(class, prefix, switchdelay_raise, float, NONE) \
+ P(class, prefix, weaponreplace, string, NONE) \
+ P(class, prefix, weaponstartoverride, float, NONE) \
+ P(class, prefix, weaponstart, float, NONE) \
+ P(class, prefix, weaponthrowable, float, NONE) \
+ END()
+ W_PROPS(X, Crylink, crylink)
+#undef X
+
ENDCLASS(Crylink)
-REGISTER_WEAPON(CRYLINK, NEW(Crylink));
-
-#define CRYLINK_SETTINGS(w_cvar,w_prop) CRYLINK_SETTINGS_LIST(w_cvar, w_prop, CRYLINK, crylink)
-#define CRYLINK_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
- w_cvar(id, sn, BOTH, ammo) \
- w_cvar(id, sn, BOTH, animtime) \
- w_cvar(id, sn, BOTH, damage) \
- w_cvar(id, sn, BOTH, edgedamage) \
- w_cvar(id, sn, BOTH, radius) \
- w_cvar(id, sn, BOTH, force) \
- w_cvar(id, sn, BOTH, spread) \
- w_cvar(id, sn, BOTH, refire) \
- w_cvar(id, sn, BOTH, speed) \
- w_cvar(id, sn, BOTH, shots) \
- w_cvar(id, sn, BOTH, bounces) \
- w_cvar(id, sn, BOTH, bouncedamagefactor) \
- w_cvar(id, sn, BOTH, middle_lifetime) \
- w_cvar(id, sn, BOTH, middle_fadetime) \
- w_cvar(id, sn, BOTH, other_lifetime) \
- w_cvar(id, sn, BOTH, other_fadetime) \
- w_cvar(id, sn, BOTH, linkexplode) \
- w_cvar(id, sn, BOTH, joindelay) \
- w_cvar(id, sn, BOTH, joinspread) \
- w_cvar(id, sn, BOTH, joinexplode) \
- w_cvar(id, sn, BOTH, joinexplode_damage) \
- w_cvar(id, sn, BOTH, joinexplode_edgedamage) \
- w_cvar(id, sn, BOTH, joinexplode_radius) \
- w_cvar(id, sn, BOTH, joinexplode_force) \
- w_cvar(id, sn, SEC, spreadtype) \
- w_cvar(id, sn, NONE, secondary) \
- w_prop(id, sn, float, reloading_ammo, reload_ammo) \
- w_prop(id, sn, float, reloading_time, reload_time) \
- w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \
- w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \
- w_prop(id, sn, string, weaponreplace, weaponreplace) \
- w_prop(id, sn, float, weaponstart, weaponstart) \
- w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \
- w_prop(id, sn, float, weaponthrowable, weaponthrowable)
+REGISTER_WEAPON(CRYLINK, crylink, NEW(Crylink));
#ifdef SVQC
-CRYLINK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
.float gravity;
.float crylink_waitrelease;
.entity crylink_lastgroup;
float i;
entity p;
- if(e == world)
- error("W_Crylink_CheckLinks: entity is world");
+ if(e == NULL)
+ error("W_Crylink_CheckLinks: entity is NULL");
if(e.classname != "spike" || wasfreed(e))
error(sprintf("W_Crylink_CheckLinks: entity is not a spike but a %s (freed: %d)", e.classname, wasfreed(e)));
{
W_Crylink_CheckLinks(next);
if(me == own.crylink_lastgroup)
- own.crylink_lastgroup = ((me == next) ? world : next);
+ own.crylink_lastgroup = ((me == next) ? NULL : next);
prev.queuenext = next;
next.queueprev = prev;
me.classname = "spike_oktoremove";
W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext);
}
-void W_Crylink_Reset()
-{SELFPARAM();
- W_Crylink_Dequeue(self);
- remove(self);
+void W_Crylink_Reset(entity this)
+{
+ W_Crylink_Dequeue(this);
+ remove(this);
}
// force projectile to explode
a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1);
if(e == e.realowner.crylink_lastgroup)
- e.realowner.crylink_lastgroup = world;
+ e.realowner.crylink_lastgroup = NULL;
float isprimary = !(e.projectiledeathtype & HITTYPE_SECONDARY);
- RadiusDamage(e, e.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * a, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * a, WEP_CVAR_BOTH(crylink, isprimary, radius), world, world, WEP_CVAR_BOTH(crylink, isprimary, force) * a, e.projectiledeathtype, other);
+ RadiusDamage(e, e.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * a, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * a, WEP_CVAR_BOTH(crylink, isprimary, radius), NULL, NULL, WEP_CVAR_BOTH(crylink, isprimary, force) * a, e.projectiledeathtype, other);
W_Crylink_LinkExplode(e.queuenext, e2);
return targ_origin;
}
-void W_Crylink_LinkJoinEffect_Think()
-{SELFPARAM();
+void W_Crylink_LinkJoinEffect_Think(entity this)
+{
// is there at least 2 projectiles very close?
entity e, p;
float n;
- e = self.owner.crylink_lastgroup;
+ e = this.owner.crylink_lastgroup;
n = 0;
if(e)
{
- if(vlen(e.origin - self.origin) < vlen(e.velocity) * frametime)
+ if(vlen2(e.origin - this.origin) < vlen2(e.velocity) * frametime)
++n;
for(p = e; (p = p.queuenext) != e; )
{
- if(vlen(p.origin - self.origin) < vlen(p.velocity) * frametime)
+ if(vlen2(p.origin - this.origin) < vlen2(p.velocity) * frametime)
++n;
}
if(n >= 2)
WEP_CVAR_BOTH(crylink, isprimary, joinexplode_edgedamage) * n,
WEP_CVAR_BOTH(crylink, isprimary, joinexplode_radius) * n,
e.realowner,
- world,
+ NULL,
WEP_CVAR_BOTH(crylink, isprimary, joinexplode_force) * n,
e.projectiledeathtype,
other
);
- Send_Effect(EFFECT_CRYLINK_JOINEXPLODE, self.origin, '0 0 0', n);
+ Send_Effect(EFFECT_CRYLINK_JOINEXPLODE, this.origin, '0 0 0', n);
}
}
}
- remove(self);
+ remove(this);
}
float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad)
while(head)
{
- if((head.takedamage != DAMAGE_NO) && (head.deadflag == DEAD_NO))
+ if((head.takedamage != DAMAGE_NO) && (!IS_DEAD(head)))
{
if(SAME_TEAM(head, projectile.realowner))
++hit_friendly;
}
// NO bounce protection, as bounces are limited!
-void W_Crylink_Touch()
-{SELFPARAM();
+void W_Crylink_Touch(entity this, entity toucher)
+{
float finalhit;
float f;
- float isprimary = !(self.projectiledeathtype & HITTYPE_SECONDARY);
- PROJECTILE_TOUCH;
+ float isprimary = !(this.projectiledeathtype & HITTYPE_SECONDARY);
+ PROJECTILE_TOUCH(this, toucher);
float a;
- a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1);
+ a = bound(0, 1 - (time - this.fade_time) * this.fade_rate, 1);
- finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO));
+ finalhit = ((this.cnt <= 0) || (toucher.takedamage != DAMAGE_NO));
if(finalhit)
f = 1;
else
if(a)
f *= a;
- float totaldamage = RadiusDamage(self, self.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * f, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * f, WEP_CVAR_BOTH(crylink, isprimary, radius), world, world, WEP_CVAR_BOTH(crylink, isprimary, force) * f, self.projectiledeathtype, other);
+ float totaldamage = RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * f, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * f, WEP_CVAR_BOTH(crylink, isprimary, radius), NULL, NULL, WEP_CVAR_BOTH(crylink, isprimary, force) * f, this.projectiledeathtype, toucher);
- if(totaldamage && ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 2) || ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 1) && !W_Crylink_Touch_WouldHitFriendly(self, WEP_CVAR_BOTH(crylink, isprimary, radius)))))
+ if(totaldamage && ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 2) || ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 1) && !W_Crylink_Touch_WouldHitFriendly(this, WEP_CVAR_BOTH(crylink, isprimary, radius)))))
{
- if(self == self.realowner.crylink_lastgroup)
- self.realowner.crylink_lastgroup = world;
- W_Crylink_LinkExplode(self.queuenext, self);
- self.classname = "spike_oktoremove";
- remove(self);
+ if(this == this.realowner.crylink_lastgroup)
+ this.realowner.crylink_lastgroup = NULL;
+ WITH(entity, other, toucher, W_Crylink_LinkExplode(this.queuenext, this));
+ this.classname = "spike_oktoremove";
+ remove(this);
return;
}
else if(finalhit)
{
// just unlink
- W_Crylink_Dequeue(self);
- remove(self);
+ W_Crylink_Dequeue(this);
+ remove(this);
return;
}
- self.cnt = self.cnt - 1;
- self.angles = vectoangles(self.velocity);
- self.owner = world;
- self.projectiledeathtype |= HITTYPE_BOUNCE;
+ this.cnt = this.cnt - 1;
+ this.angles = vectoangles(this.velocity);
+ this.owner = NULL;
+ this.projectiledeathtype |= HITTYPE_BOUNCE;
// commented out as it causes a little hitch...
//if(proj.cnt == 0)
// CSQCProjectile(proj, true, PROJECTILE_CRYLINK, true);
}
-void W_Crylink_Fadethink()
-{SELFPARAM();
- W_Crylink_Dequeue(self);
- remove(self);
+void W_Crylink_Fadethink(entity this)
+{
+ W_Crylink_Dequeue(this);
+ remove(this);
}
-void W_Crylink_Attack(Weapon thiswep)
-{SELFPARAM();
+void W_Crylink_Attack(Weapon thiswep, entity actor)
+{
float counter, shots;
entity proj, prevproj, firstproj;
vector s;
vector forward, right, up;
float maxdmg;
- W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(crylink, ammo));
+ W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(crylink, ammo));
maxdmg = WEP_CVAR_PRI(crylink, damage) * WEP_CVAR_PRI(crylink, shots);
maxdmg *= 1 + WEP_CVAR_PRI(crylink, bouncedamagefactor) * WEP_CVAR_PRI(crylink, bounces);
if(WEP_CVAR_PRI(crylink, joinexplode))
maxdmg += WEP_CVAR_PRI(crylink, joinexplode_damage);
- W_SetupShot(self, false, 2, SND(CRYLINK_FIRE), CH_WEAPON_A, maxdmg);
+ W_SetupShot(actor, false, 2, SND_CRYLINK_FIRE, CH_WEAPON_A, maxdmg);
forward = v_forward;
right = v_right;
up = v_up;
shots = WEP_CVAR_PRI(crylink, shots);
Send_Effect(EFFECT_CRYLINK_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, shots);
- proj = prevproj = firstproj = world;
+ proj = prevproj = firstproj = NULL;
for(counter = 0; counter < shots; ++counter)
{
proj = new(spike);
proj.reset = W_Crylink_Reset;
- proj.realowner = proj.owner = self;
+ proj.realowner = proj.owner = actor;
proj.bot_dodge = true;
proj.bot_dodgerating = WEP_CVAR_PRI(crylink, damage);
if(shots == 1) {
}
s = s * WEP_CVAR_PRI(crylink, spread) * g_weaponspreadfactor;
W_SetupProjVelocity_Explicit(proj, w_shotdir + right * s.y + up * s.z, v_up, WEP_CVAR_PRI(crylink, speed), 0, 0, 0, false);
- proj.touch = W_Crylink_Touch;
+ settouch(proj, W_Crylink_Touch);
- proj.think = W_Crylink_Fadethink;
+ setthink(proj, W_Crylink_Fadethink);
if(counter == 0)
{
proj.fade_time = time + WEP_CVAR_PRI(crylink, middle_lifetime);
CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
- MUTATOR_CALLHOOK(EditProjectile, self, proj);
+ MUTATOR_CALLHOOK(EditProjectile, actor, proj);
}
if(WEP_CVAR_PRI(crylink, joinspread) != 0)
{
- self.crylink_lastgroup = proj;
+ actor.crylink_lastgroup = proj;
W_Crylink_CheckLinks(proj);
- self.crylink_waitrelease = 1;
+ actor.crylink_waitrelease = 1;
}
}
-void W_Crylink_Attack2(Weapon thiswep)
-{SELFPARAM();
+void W_Crylink_Attack2(Weapon thiswep, entity actor)
+{
float counter, shots;
entity proj, prevproj, firstproj;
vector s;
vector forward, right, up;
float maxdmg;
- W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(crylink, ammo));
+ W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(crylink, ammo));
maxdmg = WEP_CVAR_SEC(crylink, damage) * WEP_CVAR_SEC(crylink, shots);
maxdmg *= 1 + WEP_CVAR_SEC(crylink, bouncedamagefactor) * WEP_CVAR_SEC(crylink, bounces);
if(WEP_CVAR_SEC(crylink, joinexplode))
maxdmg += WEP_CVAR_SEC(crylink, joinexplode_damage);
- W_SetupShot(self, false, 2, SND(CRYLINK_FIRE2), CH_WEAPON_A, maxdmg);
+ W_SetupShot(actor, false, 2, SND_CRYLINK_FIRE2, CH_WEAPON_A, maxdmg);
forward = v_forward;
right = v_right;
up = v_up;
shots = WEP_CVAR_SEC(crylink, shots);
Send_Effect(EFFECT_CRYLINK_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, shots);
- proj = prevproj = firstproj = world;
+ proj = prevproj = firstproj = NULL;
for(counter = 0; counter < shots; ++counter)
{
proj = new(spike);
proj.reset = W_Crylink_Reset;
- proj.realowner = proj.owner = self;
+ proj.realowner = proj.owner = actor;
proj.bot_dodge = true;
proj.bot_dodgerating = WEP_CVAR_SEC(crylink, damage);
if(shots == 1) {
}
W_SetupProjVelocity_Explicit(proj, s, v_up, WEP_CVAR_SEC(crylink, speed), 0, 0, 0, false);
- proj.touch = W_Crylink_Touch;
- proj.think = W_Crylink_Fadethink;
+ settouch(proj, W_Crylink_Touch);
+ setthink(proj, W_Crylink_Fadethink);
if(counter == (shots - 1) / 2)
{
proj.fade_time = time + WEP_CVAR_SEC(crylink, middle_lifetime);
CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
- MUTATOR_CALLHOOK(EditProjectile, self, proj);
+ MUTATOR_CALLHOOK(EditProjectile, actor, proj);
}
if(WEP_CVAR_SEC(crylink, joinspread) != 0)
{
- self.crylink_lastgroup = proj;
+ actor.crylink_lastgroup = proj;
W_Crylink_CheckLinks(proj);
- self.crylink_waitrelease = 2;
+ actor.crylink_waitrelease = 2;
}
}
- METHOD(Crylink, wr_aim, void(entity thiswep))
- {
- SELFPARAM();
- if(random() < 0.10)
- self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(crylink, speed), 0, WEP_CVAR_PRI(crylink, middle_lifetime), false);
- else
- self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(crylink, speed), 0, WEP_CVAR_SEC(crylink, middle_lifetime), false);
- }
- METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
- {
- if(autocvar_g_balance_crylink_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) { // forced reload
- Weapon w = get_weaponinfo(actor.weapon);
- w.wr_reload(w);
- }
-
- if(fire & 1)
- {
- if(actor.crylink_waitrelease != 1)
- if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(crylink, refire)))
- {
- W_Crylink_Attack(thiswep);
- weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(crylink, animtime), w_ready);
- }
- }
+METHOD(Crylink, wr_aim, void(entity thiswep, entity actor))
+{
+ if(random() < 0.10)
+ PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(crylink, speed), 0, WEP_CVAR_PRI(crylink, middle_lifetime), false);
+ else
+ PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, WEP_CVAR_SEC(crylink, speed), 0, WEP_CVAR_SEC(crylink, middle_lifetime), false);
+}
+METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
+{
+ if(autocvar_g_balance_crylink_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) { // forced reload
+ thiswep.wr_reload(thiswep, actor, weaponentity);
+ }
+
+ if(fire & 1)
+ {
+ if(actor.crylink_waitrelease != 1)
+ if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(crylink, refire)))
+ {
+ W_Crylink_Attack(thiswep, actor);
+ weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(crylink, animtime), w_ready);
+ }
+ }
+
+ if((fire & 2) && autocvar_g_balance_crylink_secondary)
+ {
+ if(actor.crylink_waitrelease != 2)
+ if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(crylink, refire)))
+ {
+ W_Crylink_Attack2(thiswep, actor);
+ weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(crylink, animtime), w_ready);
+ }
+ }
+
+ if((actor.crylink_waitrelease == 1 && !(fire & 1)) || (actor.crylink_waitrelease == 2 && !(fire & 2)))
+ {
+ if(!actor.crylink_lastgroup || time > actor.crylink_lastgroup.teleport_time)
+ {
+ // fired and released now!
+ if(actor.crylink_lastgroup)
+ {
+ vector pos;
+ entity linkjoineffect;
+ float isprimary = (actor.crylink_waitrelease == 1);
+
+ pos = W_Crylink_LinkJoin(actor.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed));
+
+ linkjoineffect = new(linkjoineffect);
+ setthink(linkjoineffect, W_Crylink_LinkJoinEffect_Think);
+ linkjoineffect.nextthink = time + w_crylink_linkjoin_time;
+ linkjoineffect.owner = actor;
+ setorigin(linkjoineffect, pos);
+ }
+ actor.crylink_waitrelease = 0;
+ if(!thiswep.wr_checkammo1(thiswep, actor) && !thiswep.wr_checkammo2(thiswep, actor))
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+ {
+ // ran out of ammo!
+ actor.cnt = WEP_CRYLINK.m_id;
+ PS(actor).m_switchweapon = w_getbestweapon(actor);
+ }
+ }
+ }
+}
+METHOD(Crylink, wr_checkammo1, bool(entity thiswep, entity actor))
+{
+ // don't "run out of ammo" and switch weapons while waiting for release
+ if(actor.crylink_lastgroup && actor.crylink_waitrelease)
+ return true;
- if((fire & 2) && autocvar_g_balance_crylink_secondary)
- {
- if(actor.crylink_waitrelease != 2)
- if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(crylink, refire)))
- {
- W_Crylink_Attack2(thiswep);
- weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(crylink, animtime), w_ready);
- }
- }
+ float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(crylink, ammo);
+ ammo_amount += actor.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_PRI(crylink, ammo);
+ return ammo_amount;
+}
+METHOD(Crylink, wr_checkammo2, bool(entity thiswep, entity actor))
+{
+ // don't "run out of ammo" and switch weapons while waiting for release
+ if(actor.crylink_lastgroup && actor.crylink_waitrelease)
+ return true;
- if((actor.crylink_waitrelease == 1 && !(fire & 1)) || (actor.crylink_waitrelease == 2 && !(fire & 2)))
- {
- if(!actor.crylink_lastgroup || time > actor.crylink_lastgroup.teleport_time)
- {
- // fired and released now!
- if(actor.crylink_lastgroup)
- {
- vector pos;
- entity linkjoineffect;
- float isprimary = (actor.crylink_waitrelease == 1);
-
- pos = W_Crylink_LinkJoin(actor.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed));
-
- linkjoineffect = new(linkjoineffect);
- linkjoineffect.think = W_Crylink_LinkJoinEffect_Think;
- linkjoineffect.nextthink = time + w_crylink_linkjoin_time;
- linkjoineffect.owner = actor;
- setorigin(linkjoineffect, pos);
- }
- actor.crylink_waitrelease = 0;
- if(!thiswep.wr_checkammo1(thiswep) && !thiswep.wr_checkammo2(thiswep))
- if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
- {
- // ran out of ammo!
- actor.cnt = WEP_CRYLINK.m_id;
- actor.switchweapon = w_getbestweapon(actor);
- }
- }
- }
- }
- METHOD(Crylink, wr_init, void(entity thiswep))
- {
- CRYLINK_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
- }
- METHOD(Crylink, wr_checkammo1, bool(entity thiswep))
- {
- SELFPARAM();
- // don't "run out of ammo" and switch weapons while waiting for release
- if(self.crylink_lastgroup && self.crylink_waitrelease)
- return true;
-
- float ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_PRI(crylink, ammo);
- ammo_amount += self.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_PRI(crylink, ammo);
- return ammo_amount;
- }
- METHOD(Crylink, wr_checkammo2, bool(entity thiswep))
- {
- SELFPARAM();
- // don't "run out of ammo" and switch weapons while waiting for release
- if(self.crylink_lastgroup && self.crylink_waitrelease)
- return true;
-
- float ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_SEC(crylink, ammo);
- ammo_amount += self.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_SEC(crylink, ammo);
- return ammo_amount;
- }
- METHOD(Crylink, wr_config, void(entity thiswep))
- {
- CRYLINK_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
- }
- METHOD(Crylink, wr_reload, void(entity thiswep))
- {
- W_Reload(self, min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo)), SND(RELOAD));
- }
- METHOD(Crylink, wr_suicidemessage, int(entity thiswep))
- {
- return WEAPON_CRYLINK_SUICIDE;
- }
- METHOD(Crylink, wr_killmessage, int(entity thiswep))
- {
- return WEAPON_CRYLINK_MURDER;
- }
+ float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(crylink, ammo);
+ ammo_amount += actor.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_SEC(crylink, ammo);
+ return ammo_amount;
+}
+METHOD(Crylink, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
+{
+ W_Reload(actor, min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo)), SND_RELOAD);
+}
+METHOD(Crylink, wr_suicidemessage, Notification(entity thiswep))
+{
+ return WEAPON_CRYLINK_SUICIDE;
+}
+METHOD(Crylink, wr_killmessage, Notification(entity thiswep))
+{
+ return WEAPON_CRYLINK_MURDER;
+}
#endif
#ifdef CSQC
- METHOD(Crylink, wr_impacteffect, void(entity thiswep))
- {
- SELFPARAM();
- vector org2;
- org2 = w_org + w_backoff * 2;
- if(w_deathtype & HITTYPE_SECONDARY)
- {
- pointparticles(EFFECT_CRYLINK_IMPACT2, org2, '0 0 0', 1);
- if(!w_issilent)
- sound(self, CH_SHOTS, SND_CRYLINK_IMPACT2, VOL_BASE, ATTN_NORM);
- }
- else
- {
- pointparticles(EFFECT_CRYLINK_IMPACT, org2, '0 0 0', 1);
- if(!w_issilent)
- sound(self, CH_SHOTS, SND_CRYLINK_IMPACT, VOL_BASE, ATTN_NORM);
- }
- }
+METHOD(Crylink, wr_impacteffect, void(entity thiswep, entity actor))
+{
+ vector org2;
+ org2 = w_org + w_backoff * 2;
+ if(w_deathtype & HITTYPE_SECONDARY)
+ {
+ pointparticles(EFFECT_CRYLINK_IMPACT2, org2, '0 0 0', 1);
+ if(!w_issilent)
+ sound(actor, CH_SHOTS, SND_CRYLINK_IMPACT2, VOL_BASE, ATTN_NORM);
+ }
+ else
+ {
+ pointparticles(EFFECT_CRYLINK_IMPACT, org2, '0 0 0', 1);
+ if(!w_issilent)
+ sound(actor, CH_SHOTS, SND_CRYLINK_IMPACT, VOL_BASE, ATTN_NORM);
+ }
+}
#endif
#endif