============================================*/
-.string aiment_classname;
-.float aiment_deadflag;
-void SetMovetypeFollow(entity ent, entity e)
-{
- // FIXME this may not be warpzone aware
- ent.movetype = MOVETYPE_FOLLOW; // make the hole follow
- ent.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid - this means this cannot be teleported by warpzones any more! Instead, we must notice when our owner gets teleported.
- ent.aiment = e; // make the hole follow bmodel
- ent.punchangle = e.angles; // the original angles of bmodel
- ent.view_ofs = ent.origin - e.origin; // relative origin
- ent.v_angle = ent.angles - e.angles; // relative angles
- ent.aiment_classname = strzone(e.classname);
- ent.aiment_deadflag = e.deadflag;
-}
-void UnsetMovetypeFollow(entity ent)
-{
- ent.movetype = MOVETYPE_FLY;
- PROJECTILE_MAKETRIGGER(ent);
- ent.aiment = world;
-}
-float LostMovetypeFollow(entity ent)
-{
-/*
- if(ent.movetype != MOVETYPE_FOLLOW)
- if(ent.aiment)
- error("???");
-*/
- if(ent.aiment)
- {
- if(ent.aiment.classname != ent.aiment_classname)
- return 1;
- if(ent.aiment.deadflag != ent.aiment_deadflag)
- return 1;
- }
- return 0;
-}
-
.float hook_length;
.float hook_switchweapon;
//pl.disableclientprediction = FALSE;
}
+void GrapplingHookReset(void)
+{
+ if(self.realowner.hook == self)
+ RemoveGrapplingHook(self.owner);
+ else // in any case:
+ remove(self);
+}
+
void GrapplingHookThink();
void GrapplingHook_Stop()
{
pointparticles(particleeffectnum("grapple_impact"), self.origin, '0 0 0', 1);
- sound (self, CHAN_PROJECTILE, "weapons/hook_impact.wav", VOL_BASE, ATTN_NORM);
+ sound (self, CH_SHOTS, "weapons/hook_impact.wav", VOL_BASE, ATTN_NORM);
self.state = 1;
self.think = GrapplingHookThink;
{
WriteByte(MSG_ENTITY, ENT_CLIENT_HOOK);
sf = sf & 0x7F;
- if(sound_allowed(MSG_BROADCAST, self.owner))
+ if(sound_allowed(MSG_BROADCAST, self.realowner))
sf |= 0x80;
WriteByte(MSG_ENTITY, sf);
if(sf & 1)
{
- WriteByte(MSG_ENTITY, num_for_edict(self.owner));
+ WriteByte(MSG_ENTITY, num_for_edict(self.realowner));
}
if(sf & 2)
{
{
float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch, s;
vector dir, org, end, v0, dv, v, myorg, vs;
- if(self.owner.health <= 0 || self.owner.hook != self) // how did that happen?
- { // well, better fix it anyway
- remove(self);
+ if(self.realowner.hook != self) // how did that happen?
+ {
+ error("Owner lost the hook!\n");
return;
}
- if(LostMovetypeFollow(self))
+ if(LostMovetypeFollow(self) || intermission_running)
{
- RemoveGrapplingHook(self.owner);
+ RemoveGrapplingHook(self.realowner);
return;
}
if(self.aiment)
self.nextthink = time;
- s = self.owner.cvar_cl_gunalign;
+ s = self.realowner.cvar_cl_gunalign;
if(s != 1 && s != 2 && s != 4)
s = 3; // default value
--s;
vs = hook_shotorigin[s];
- makevectors(self.owner.v_angle);
- org = self.owner.origin + self.owner.view_ofs + v_forward * vs_x + v_right * -vs_y + v_up * vs_z;
- myorg = WarpZone_RefSys_TransformOrigin(self.owner, self, org);
+ makevectors(self.realowner.v_angle);
+ org = self.realowner.origin + self.realowner.view_ofs + v_forward * vs_x + v_right * -vs_y + v_up * vs_z;
+ myorg = WarpZone_RefSys_TransformOrigin(self.realowner, self, org);
if(self.hook_length < 0)
self.hook_length = vlen(myorg - self.origin);
if(self.state == 1)
{
- pullspeed = cvar("g_balance_grapplehook_speed_pull");//2000;
+ pullspeed = autocvar_g_balance_grapplehook_speed_pull;//2000;
// speed the rope is pulled with
- rubberforce = cvar("g_balance_grapplehook_force_rubber");//2000;
+ rubberforce = autocvar_g_balance_grapplehook_force_rubber;//2000;
// force the rope will use if it is stretched
- rubberforce_overstretch = cvar("g_balance_grapplehook_force_rubber_overstretch");//1000;
+ rubberforce_overstretch = autocvar_g_balance_grapplehook_force_rubber_overstretch;//1000;
// force the rope will use if it is stretched
- minlength = cvar("g_balance_grapplehook_length_min");//100;
+ minlength = autocvar_g_balance_grapplehook_length_min;//100;
// minimal rope length
// if the rope goes below this length, it isn't pulled any more
- ropestretch = cvar("g_balance_grapplehook_stretch");//400;
+ ropestretch = autocvar_g_balance_grapplehook_stretch;//400;
// if the rope is stretched by more than this amount, more rope is
// given to you again
- ropeairfriction = cvar("g_balance_grapplehook_airfriction");//0.2
+ ropeairfriction = autocvar_g_balance_grapplehook_airfriction;//0.2
// while hanging on the rope, this friction component will help you a
// bit to control the rope
dist = vlen(dir);
dir = normalize(dir);
- if(cvar("g_grappling_hook_tarzan"))
+ if(autocvar_g_grappling_hook_tarzan)
{
- v = v0 = WarpZone_RefSys_TransformVelocity(self.owner, self, self.owner.velocity);
+ v = v0 = WarpZone_RefSys_TransformVelocity(self.realowner, self, self.realowner.velocity);
// first pull the rope...
- if(self.owner.hook_state & HOOK_PULLING)
+ if(self.realowner.hook_state & HOOK_PULLING)
{
newlength = self.hook_length;
newlength = max(newlength - pullspeed * frametime, minlength);
self.hook_length = newlength;
}
- if(self.owner.hook_state & HOOK_RELEASING)
+ if(self.realowner.hook_state & HOOK_RELEASING)
{
newlength = dist;
self.hook_length = newlength;
v = v + frametime * dir * spd * rubberforce;
dv = ((v - v0) * dir) * dir;
- if(cvar("g_grappling_hook_tarzan") >= 2)
+ if(autocvar_g_grappling_hook_tarzan >= 2)
{
if(self.aiment.movetype == MOVETYPE_WALK)
{
v = v - dv * 0.5;
self.aiment.velocity = self.aiment.velocity - dv * 0.5;
self.aiment.flags &~= FL_ONGROUND;
- self.aiment.pusher = self.owner;
- self.aiment.pushltime = time + cvar("g_maxpushtime");
+ self.aiment.pusher = self.realowner;
+ self.aiment.pushltime = time + autocvar_g_maxpushtime;
}
}
- self.owner.flags &~= FL_ONGROUND;
+ self.realowner.flags &~= FL_ONGROUND;
}
- self.owner.velocity = WarpZone_RefSys_TransformVelocity(self, self.owner, v);
+ self.realowner.velocity = WarpZone_RefSys_TransformVelocity(self, self.realowner, v);
}
else
{
spd = pullspeed;
if(spd < 50)
spd = 0;
- self.owner.velocity = dir*spd;
- self.owner.movetype = MOVETYPE_FLY;
+ self.realowner.velocity = dir*spd;
+ self.realowner.movetype = MOVETYPE_FLY;
- self.owner.flags &~= FL_ONGROUND;
+ self.realowner.flags &~= FL_ONGROUND;
}
}
makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0');
- myorg = WarpZone_RefSys_TransformOrigin(self, self.owner, self.origin); // + v_forward * (-9);
+ myorg = WarpZone_RefSys_TransformOrigin(self, self.realowner, self.origin); // + v_forward * (-9);
if(myorg != self.hook_start)
{
void GrapplingHookTouch (void)
{
- if(SUB_OwnerCheck())
- return;
- if(SUB_NoImpactCheck())
- {
- RemoveGrapplingHook(self.owner);
- return;
- }
PROJECTILE_TOUCH;
GrapplingHook_Stop();
WarpZone_RefSys_BeginAddingIncrementally(self, self.aiment);
}
- //self.owner.disableclientprediction = TRUE;
+ //self.realowner.disableclientprediction = TRUE;
}
void GrapplingHook_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
- if(self.health > 0)
+ if(self.health <= 0)
+ return;
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+ return; // g_balance_projectiledamage says to halt
+
+ self.health = self.health - damage;
+
+ if (self.health <= 0)
{
- self.health = self.health - damage;
- if (self.health <= 0)
+ if(attacker != self.realowner)
{
- if(attacker != self.owner)
- {
- self.owner.pusher = attacker;
- self.owner.pushltime = time + cvar("g_maxpushtime");
- }
- RemoveGrapplingHook(self.owner);
+ self.realowner.pusher = attacker;
+ self.realowner.pushltime = time + autocvar_g_maxpushtime;
}
+ RemoveGrapplingHook(self.realowner);
}
}
void FireGrapplingHook (void)
{
- local entity missile;
- local vector org;
+ entity missile;
+ vector org;
float s;
vector vs;
if((arena_roundbased && time < warmup) || (time < game_starttime))
return;
+ if(self.freezetag_frozen)
+ return;
+
+ if(self.vehicle)
+ return;
+
makevectors(self.v_angle);
s = self.cvar_cl_gunalign;
--s;
vs = hook_shotorigin[s];
- // UGLY WORKAROUND: play this on CHAN_WEAPON2 so it can't cut off fire sounds
- sound (self, CHAN_WEAPON2, "weapons/hook_fire.wav", VOL_BASE, ATTN_NORM);
+ // UGLY WORKAROUND: play this on CH_WEAPON_B so it can't cut off fire sounds
+ sound (self, CH_WEAPON_B, "weapons/hook_fire.wav", VOL_BASE, ATTN_NORM);
org = self.origin + self.view_ofs + v_forward * vs_x + v_right * -vs_y + v_up * vs_z;
tracebox(self.origin + self.view_ofs, '-3 -3 -3', '3 3 3', org, MOVE_NORMAL, self);
pointparticles(particleeffectnum("grapple_muzzleflash"), org, '0 0 0', 1);
missile = WarpZone_RefSys_SpawnSameRefSys(self);
- missile.owner = self;
+ missile.owner = missile.realowner = self;
self.hook = missile;
+ missile.reset = GrapplingHookReset;
missile.classname = "grapplinghook";
+ missile.flags = FL_PROJECTILE;
missile.movetype = MOVETYPE_FLY;
PROJECTILE_MAKETRIGGER(missile);
missile.state = 0; // not latched onto anything
- W_SetupProjectileVelocityEx(missile, v_forward, v_up, cvar("g_balance_grapplehook_speed_fly"), 0, 0, 0, FALSE);
+ W_SetupProjectileVelocityEx(missile, v_forward, v_up, autocvar_g_balance_grapplehook_speed_fly, 0, 0, 0, FALSE);
missile.angles = vectoangles (missile.velocity);
//missile.glow_color = 250; // 244, 250
//missile.glow_size = 120;
missile.touch = GrapplingHookTouch;
missile.think = GrapplingHookThink;
- missile.nextthink = time + 0.1;
+ missile.nextthink = time;
missile.effects = /*EF_FULLBRIGHT | EF_ADDITIVE |*/ EF_LOWPRECISION;
- missile.health = cvar("g_balance_grapplehook_health");//120
+ missile.health = autocvar_g_balance_grapplehook_health;//120
missile.event_damage = GrapplingHook_Damage;
missile.takedamage = DAMAGE_AIM;
missile.damageforcescale = 0;
+ missile.damagedbycontents = (autocvar_g_balance_grapplehook_damagedbycontents);
missile.hook_start = missile.hook_end = missile.origin;
void GrapplingHookFrame()
{
- if(g_grappling_hook && timeoutStatus != 2 && self.weapon != WEP_HOOK)
+ if(g_grappling_hook && timeout_status != TIMEOUT_ACTIVE && self.weapon != WEP_HOOK)
{
// offhand hook controls
if(self.BUTTON_HOOK)