self.movetype = MOVETYPE_NONE;
}
-void W_Hook_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{SELFPARAM();
- if(self.health <= 0)
+void W_Hook_Explode2_use(entity this, entity actor, entity trigger)
+{
+ WITHSELF(this, W_Hook_Explode2());
+}
+
+void W_Hook_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+ if(this.health <= 0)
return;
- if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+ if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions
return; // g_projectiles_damage says to halt
- self.health = self.health - damage;
+ this.health = this.health - damage;
- if(self.health <= 0)
- W_PrepareExplosionByDamage(self.realowner, W_Hook_Explode2);
+ if(this.health <= 0)
+ W_PrepareExplosionByDamage(this, this.realowner, W_Hook_Explode2);
}
void W_Hook_Touch2()
{SELFPARAM();
PROJECTILE_TOUCH;
- self.use();
+ this.use(this, NULL, NULL);
}
void W_Hook_Attack2(Weapon thiswep, entity actor)
{
//W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hook, ammo)); // WEAPONTODO: Figure out how to handle ammo with hook secondary (gravitybomb)
- W_SetupShot(actor, false, 4, SND(HOOKBOMB_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(hook, damage));
+ W_SetupShot(actor, false, 4, SND_HOOKBOMB_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hook, damage));
entity gren = new(hookbomb);
gren.owner = gren.realowner = actor;
gren.nextthink = time + WEP_CVAR_SEC(hook, lifetime);
gren.think = adaptor_think2use_hittype_splash;
- gren.use = W_Hook_Explode2;
+ gren.use = W_Hook_Explode2_use;
gren.touch = W_Hook_Touch2;
gren.takedamage = DAMAGE_YES;
MUTATOR_CALLHOOK(EditProjectile, actor, gren);
}
- METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
- {
- if (fire & 1) {
- if(!actor.hook)
- if(!(actor.hook_state & HOOK_WAITING_FOR_RELEASE))
- if(time > actor.hook_refire)
- if(weapon_prepareattack(thiswep, actor, weaponentity, false, -1))
- {
- W_DecreaseAmmo(thiswep, actor, thiswep.ammo_factor * WEP_CVAR_PRI(hook, ammo));
- actor.hook_state |= HOOK_FIRING;
- actor.hook_state |= HOOK_WAITING_FOR_RELEASE;
- weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hook, animtime), w_ready);
- }
- } else {
- actor.hook_state |= HOOK_REMOVING;
- actor.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
- }
+METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
+{
+ SELFPARAM();
+ if (fire & 1) {
+ if(!actor.hook)
+ if(!(actor.hook_state & HOOK_WAITING_FOR_RELEASE))
+ if(time > actor.hook_refire)
+ if(weapon_prepareattack(thiswep, actor, weaponentity, false, -1))
+ {
+ W_DecreaseAmmo(thiswep, actor, thiswep.ammo_factor * WEP_CVAR_PRI(hook, ammo));
+ actor.hook_state |= HOOK_FIRING;
+ actor.hook_state |= HOOK_WAITING_FOR_RELEASE;
+ weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hook, animtime), w_ready);
+ }
+ } else {
+ actor.hook_state |= HOOK_REMOVING;
+ actor.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
+ }
- if(fire & 2)
- {
- if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(hook, refire)))
- {
- W_Hook_Attack2(thiswep, actor);
- weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hook, animtime), w_ready);
- }
- }
+ if(fire & 2)
+ {
+ if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(hook, refire)))
+ {
+ W_Hook_Attack2(thiswep, actor);
+ weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hook, animtime), w_ready);
+ }
+ }
- if(actor.hook)
- {
- // if hooked, no bombs, and increase the timer
- actor.hook_refire = max(actor.hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor());
+ if(actor.hook)
+ {
+ // if hooked, no bombs, and increase the timer
+ actor.hook_refire = max(actor.hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor());
- // hook also inhibits health regeneration, but only for 1 second
- if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
- actor.pauseregen_finished = max(actor.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
- }
+ // hook also inhibits health regeneration, but only for 1 second
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+ actor.pauseregen_finished = max(actor.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
+ }
- if(actor.hook && actor.hook.state == 1)
- {
- float hooked_time_max = WEP_CVAR_PRI(hook, hooked_time_max);
- if(hooked_time_max > 0)
- {
- if( time > actor.hook_time_hooked + hooked_time_max )
- actor.hook_state |= HOOK_REMOVING;
- }
-
- float hooked_fuel = thiswep.ammo_factor * WEP_CVAR_PRI(hook, hooked_ammo);
- if(hooked_fuel > 0)
- {
- if( time > actor.hook_time_fueldecrease )
- {
- if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
- {
- if( actor.ammo_fuel >= (time - actor.hook_time_fueldecrease) * hooked_fuel )
- {
- W_DecreaseAmmo(thiswep, actor, (time - actor.hook_time_fueldecrease) * hooked_fuel);
- actor.hook_time_fueldecrease = time;
- // decrease next frame again
- }
- else
- {
- actor.ammo_fuel = 0;
- actor.hook_state |= HOOK_REMOVING;
- W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
- }
- }
- }
- }
- }
- else
- {
- actor.hook_time_hooked = time;
- actor.hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
- }
+ if(actor.hook && actor.hook.state == 1)
+ {
+ float hooked_time_max = WEP_CVAR_PRI(hook, hooked_time_max);
+ if(hooked_time_max > 0)
+ {
+ if( time > actor.hook_time_hooked + hooked_time_max )
+ actor.hook_state |= HOOK_REMOVING;
+ }
+
+ float hooked_fuel = thiswep.ammo_factor * WEP_CVAR_PRI(hook, hooked_ammo);
+ if(hooked_fuel > 0)
+ {
+ if( time > actor.hook_time_fueldecrease )
+ {
+ if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+ {
+ if( actor.ammo_fuel >= (time - actor.hook_time_fueldecrease) * hooked_fuel )
+ {
+ W_DecreaseAmmo(thiswep, actor, (time - actor.hook_time_fueldecrease) * hooked_fuel);
+ actor.hook_time_fueldecrease = time;
+ // decrease next frame again
+ }
+ else
+ {
+ actor.ammo_fuel = 0;
+ actor.hook_state |= HOOK_REMOVING;
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ actor.hook_time_hooked = time;
+ actor.hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
+ }
- actor.hook_state = BITSET(actor.hook_state, HOOK_PULLING, (!actor.BUTTON_CROUCH || !autocvar_g_balance_grapplehook_crouchslide));
+ actor.hook_state = BITSET(actor.hook_state, HOOK_PULLING, (!PHYS_INPUT_BUTTON_CROUCH(actor) || !autocvar_g_balance_grapplehook_crouchslide));
- if (actor.hook_state & HOOK_FIRING)
- {
- if (actor.hook)
- RemoveGrapplingHook(actor);
- WITH(entity, self, actor, FireGrapplingHook());
- actor.hook_state &= ~HOOK_FIRING;
- actor.hook_refire = max(actor.hook_refire, time + autocvar_g_balance_grapplehook_refire * W_WeaponRateFactor());
- }
- else if (actor.hook_state & HOOK_REMOVING)
- {
- if (actor.hook)
- RemoveGrapplingHook(actor);
- actor.hook_state &= ~HOOK_REMOVING;
- }
- }
- METHOD(Hook, wr_setup, void(entity thiswep))
- {
- self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
- }
- METHOD(Hook, wr_checkammo1, bool(Hook thiswep))
- {
- if (!thiswep.ammo_factor) return true;
- if(self.hook)
- return self.ammo_fuel > 0;
- else
- return self.ammo_fuel >= WEP_CVAR_PRI(hook, ammo);
- }
- METHOD(Hook, wr_checkammo2, bool(Hook thiswep))
- {
- // infinite ammo for now
- return true; // self.ammo_cells >= WEP_CVAR_SEC(hook, ammo); // WEAPONTODO: see above
- }
- METHOD(Hook, wr_resetplayer, void(entity thiswep))
- {
- RemoveGrapplingHook(self);
- self.hook_time = 0;
- self.hook_refire = time;
- }
- METHOD(Hook, wr_suicidemessage, int(entity thiswep))
- {
- return false;
- }
- METHOD(Hook, wr_killmessage, int(entity thiswep))
- {
- return WEAPON_HOOK_MURDER;
- }
+ if (actor.hook_state & HOOK_FIRING)
+ {
+ if (actor.hook)
+ RemoveGrapplingHook(actor);
+ WITHSELF(actor, FireGrapplingHook());
+ actor.hook_state &= ~HOOK_FIRING;
+ actor.hook_refire = max(actor.hook_refire, time + autocvar_g_balance_grapplehook_refire * W_WeaponRateFactor());
+ }
+ else if (actor.hook_state & HOOK_REMOVING)
+ {
+ if (actor.hook)
+ RemoveGrapplingHook(actor);
+ actor.hook_state &= ~HOOK_REMOVING;
+ }
+}
+METHOD(Hook, wr_setup, void(entity thiswep))
+{
+ SELFPARAM();
+ self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
+}
+METHOD(Hook, wr_checkammo1, bool(Hook thiswep))
+{
+ SELFPARAM();
+ if (!thiswep.ammo_factor) return true;
+ if(self.hook)
+ return self.ammo_fuel > 0;
+ else
+ return self.ammo_fuel >= WEP_CVAR_PRI(hook, ammo);
+}
+METHOD(Hook, wr_checkammo2, bool(Hook thiswep))
+{
+ // infinite ammo for now
+ return true; // self.ammo_cells >= WEP_CVAR_SEC(hook, ammo); // WEAPONTODO: see above
+}
+METHOD(Hook, wr_resetplayer, void(entity thiswep))
+{
+ SELFPARAM();
+ RemoveGrapplingHook(self);
+ self.hook_time = 0;
+ self.hook_refire = time;
+}
+METHOD(Hook, wr_killmessage, Notification(entity thiswep))
+{
+ return WEAPON_HOOK_MURDER;
+}
#endif
#ifdef CSQC
- METHOD(Hook, wr_impacteffect, void(entity thiswep))
- {
- vector org2;
- org2 = w_org + w_backoff * 2;
- pointparticles(EFFECT_HOOK_EXPLODE, org2, '0 0 0', 1);
- if(!w_issilent)
- sound(self, CH_SHOTS, SND_HOOKBOMB_IMPACT, VOL_BASE, ATTN_NORM);
- }
+METHOD(Hook, wr_impacteffect, void(entity thiswep))
+{
+ SELFPARAM();
+ vector org2;
+ org2 = w_org + w_backoff * 2;
+ pointparticles(EFFECT_HOOK_EXPLODE, org2, '0 0 0', 1);
+ if(!w_issilent)
+ sound(self, CH_SHOTS, SND_HOOKBOMB_IMPACT, VOL_BASE, ATTN_NORM);
+}
#endif
#ifdef CSQC
-#include "../../../lib/csqcmodel/interpolate.qh"
-#include "../../../lib/warpzone/common.qh"
+#include <lib/csqcmodel/interpolate.qh>
+#include <lib/warpzone/common.qh>
+
+float autocvar_cl_grapplehook_alpha = 1;
void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg);
vector vs;
float intensity, offset;
- if(self.teleport_time)
- if(time > self.teleport_time)
+ if(this.teleport_time)
+ if(time > this.teleport_time)
{
- sound (self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM); // safeguard
- self.teleport_time = 0;
+ sound (this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM); // safeguard
+ this.teleport_time = 0;
}
InterpolateOrigin_Do(this);
int s = W_GetGunAlignment(world);
- switch(self.HookType)
+ switch(this.HookType)
{
default:
case NET_ENT_CLIENT_HOOK:
break;
}
- if((self.owner.sv_entnum == player_localentnum - 1) && autocvar_chase_active <= 0)
+ if((this.owner.sv_entnum == player_localentnum - 1) && autocvar_chase_active <= 0)
{
- switch(self.HookType)
+ switch(this.HookType)
{
default:
case NET_ENT_CLIENT_HOOK:
a = view_origin + view_forward * vs.x + view_right * -vs.y + view_up * vs.z;
- b = self.origin;
+ b = this.origin;
break;
case NET_ENT_CLIENT_ARC_BEAM:
- if(self.HookRange)
- b = view_origin + view_forward * self.HookRange;
+ if(this.HookRange)
+ b = view_origin + view_forward * this.HookRange;
else
- b = view_origin + view_forward * vlen(self.velocity - self.origin); // honor original length of beam!
+ b = view_origin + view_forward * vlen(this.velocity - this.origin); // honor original length of beam!
WarpZone_TraceLine(view_origin, b, MOVE_NORMAL, world);
b = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
a = view_origin + view_forward * vs.x + view_right * -vs.y + view_up * vs.z;
}
else
{
- switch(self.HookType)
+ switch(this.HookType)
{
default:
case NET_ENT_CLIENT_HOOK:
- a = self.velocity;
- b = self.origin;
+ a = this.velocity;
+ b = this.origin;
break;
case NET_ENT_CLIENT_ARC_BEAM:
- a = self.origin;
- b = self.velocity;
+ a = this.origin;
+ b = this.velocity;
break;
}
}
- t = entcs_GetTeamColor(self.owner.sv_entnum);
+ t = entcs_GetTeamColor(this.owner.sv_entnum);
- switch(self.HookType)
+ switch(this.HookType)
{
default:
case NET_ENT_CLIENT_HOOK:
- intensity = 1;
+ intensity = autocvar_cl_grapplehook_alpha;
offset = 0;
switch(t)
{
case NUM_TEAM_2: tex = "particles/hook_blue"; rgb = '0.3 0.3 1'; break;
case NUM_TEAM_3: tex = "particles/hook_yellow"; rgb = '1 1 0.3'; break;
case NUM_TEAM_4: tex = "particles/hook_pink"; rgb = '1 0.3 1'; break;
- default: tex = "particles/hook_white"; rgb = entcs_GetColor(self.sv_entnum - 1); break;
+ default: tex = "particles/hook_white"; rgb = entcs_GetColor(this.sv_entnum - 1); break;
}
break;
case NET_ENT_CLIENT_ARC_BEAM: // todo
- intensity = bound(0.2, 1 + Noise_Pink(self, frametime) * 1 + Noise_Burst(self, frametime, 0.03) * 0.3, 2);
- offset = Noise_Brown(self, frametime) * 10;
+ intensity = bound(0.2, 1 + Noise_Pink(this, frametime) * 1 + Noise_Burst(this, frametime, 0.03) * 0.3, 2);
+ offset = Noise_Brown(this, frametime) * 10;
tex = "particles/lgbeam";
rgb = '1 1 1';
break;
Draw_GrapplingHook_trace_callback_rnd = offset;
Draw_GrapplingHook_trace_callback_rgb = rgb;
Draw_GrapplingHook_trace_callback_a = intensity;
- WarpZone_TraceBox_ThroughZone(a, '0 0 0', '0 0 0', b, ((self.HookType == NET_ENT_CLIENT_HOOK) ? MOVE_NOTHING : MOVE_NORMAL), world, world, Draw_GrapplingHook_trace_callback);
+ WarpZone_TraceBox_ThroughZone(a, '0 0 0', '0 0 0', b, ((this.HookType == NET_ENT_CLIENT_HOOK) ? MOVE_NOTHING : MOVE_NORMAL), world, world, Draw_GrapplingHook_trace_callback);
Draw_GrapplingHook_trace_callback_tex = string_null;
atrans = WarpZone_TransformOrigin(WarpZone_trace_transform, a);
- switch(self.HookType)
+ switch(this.HookType)
{
default:
case NET_ENT_CLIENT_HOOK:
- if(vlen(trace_endpos - atrans) > 0.5)
+ if(vdist(trace_endpos - atrans, >, 0.5))
{
- setorigin(self, trace_endpos); // hook endpoint!
- self.angles = vectoangles(trace_endpos - atrans);
- self.drawmask = MASK_NORMAL;
+ setorigin(this, trace_endpos); // hook endpoint!
+ this.angles = vectoangles(trace_endpos - atrans);
+ this.drawmask = MASK_NORMAL;
}
else
{
- self.drawmask = 0;
+ this.drawmask = 0;
}
break;
case NET_ENT_CLIENT_ARC_BEAM:
- setorigin(self, a); // beam origin!
+ setorigin(this, a); // beam origin!
break;
}
- switch(self.HookType)
+ switch(this.HookType)
{
default:
case NET_ENT_CLIENT_HOOK:
}
}
-void Remove_GrapplingHook()
-{SELFPARAM();
- sound (self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
+void Remove_GrapplingHook(entity this)
+{
+ sound (this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
+
+ if(csqcplayer && csqcplayer.hook == this)
+ csqcplayer.hook = NULL;
}
NET_HANDLE(ENT_CLIENT_HOOK, bool bIsNew)
int myowner = ReadByte();
self.owner = playerslots[myowner - 1];
self.sv_entnum = myowner;
+ if(csqcplayer && myowner == player_localentnum)
+ csqcplayer.hook = self;
switch(self.HookType)
{
default: