if(DIFF_TEAM(frag_attacker, frag_target.realowner))
{
Damage (frag_target.realowner, frag_attacker, frag_attacker, 5, WEP_HOOK.m_id | HITTYPE_SPLASH, frag_target.realowner.origin, '0 0 0');
- RemoveGrapplingHook(frag_target.realowner);
+ RemoveHook(frag_target);
return; // dead
}
}
IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
{
- RemoveGrapplingHook(it.realowner);
+ RemoveHook(it);
});
delete(this);
{
IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
{
- RemoveGrapplingHook(it.realowner);
+ RemoveHook(it);
});
delete(this);
return;
// set crouched
bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
- if(this.hook && !wasfreed(this.hook))
- do_crouch = false;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ entity wep = viewmodels[slot];
+ if(wep.hook && !wasfreed(wep.hook))
+ {
+ do_crouch = false;
+ break; // don't bother checking the others
+ }
+ }
if(this.waterlevel >= WATERLEVEL_SWIMMING)
do_crouch = false;
if(hud != HUD_NORMAL)
this.wasFlying = false;
if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
if (time < this.ladder_time) return;
- if (this.hook) return;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(this.(weaponentity).hook)
+ return;
+ }
this.nextstep = time + 0.3 + random() * 0.1;
trace_dphitq3surfaceflags = 0;
tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
#ifdef SVQC
if(IS_PLAYER(toucher))
- RemoveGrapplingHook(toucher);
+ RemoveGrapplingHooks(toucher);
#endif
entity e;
}
else return;
- RemoveGrapplingHook(pl);
+ RemoveGrapplingHooks(pl);
veh.vehicle_ammo1 = 0;
veh.vehicle_ammo2 = 0;
if(this.vehicle_controller)
this.team = this.vehicle_controller.team;
- FOREACH_CLIENT(IS_PLAYER(it) && it.hook.aiment == this, RemoveGrapplingHook(it));
+ FOREACH_CLIENT(IS_PLAYER(it),
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(it.(weaponentity).hook.aiment == this)
+ RemoveHook(it.(weaponentity).hook);
+ }
+ });
vehicles_reset_colors(this);
player.vehicle_energy = vehic.vehicle_energy;
UNSET_ONGROUND(player);
- RemoveGrapplingHook(player);
+ RemoveGrapplingHooks(player);
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
if (this.movedir.x >= 0)
{
- int algn = STAT(GUNALIGN, this.owner);
+ //int algn = STAT(GUNALIGN, this.owner);
+ int algn = W_GunAlign(this, STAT(GUNALIGN, this.owner));
+ this.m_gunalign = algn;
vector v = this.movedir;
this.movedir = shotorg_adjust(v, false, false, algn);
this.view_ofs = shotorg_adjust(v, false, true, algn) - v;
entity gunaligns[5];
#endif
+.int m_gunalign;
+
//.int weapon; // current weapon
.string weaponname; // name of .weapon
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(!actor.(weaponentity).hook)
+ if(!(actor.(weaponentity).hook_state & HOOK_WAITING_FOR_RELEASE))
+ if(time > actor.(weaponentity).hook_refire)
if(weapon_prepareattack(thiswep, actor, weaponentity, false, -1))
{
W_DecreaseAmmo(thiswep, actor, thiswep.ammo_factor * WEP_CVAR_PRI(hook, ammo), weaponentity);
- actor.hook_state |= HOOK_FIRING;
- actor.hook_state |= HOOK_WAITING_FOR_RELEASE;
+ actor.(weaponentity).hook_state |= HOOK_FIRING;
+ actor.(weaponentity).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;
+ actor.(weaponentity).hook_state |= HOOK_REMOVING;
+ actor.(weaponentity).hook_state &= ~HOOK_WAITING_FOR_RELEASE;
}
if(fire & 2)
}
}
- if(actor.hook)
+ if(actor.(weaponentity).hook)
{
// if hooked, no bombs, and increase the timer
- actor.hook_refire = max(actor.hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor(actor));
+ actor.(weaponentity).hook_refire = max(actor.(weaponentity).hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor(actor));
// 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)
+ if(actor.(weaponentity).hook && actor.(weaponentity).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;
+ if( time > actor.(weaponentity).hook_time_hooked + hooked_time_max )
+ actor.(weaponentity).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( time > actor.(weaponentity).hook_time_fueldecrease )
{
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- if( actor.ammo_fuel >= (time - actor.hook_time_fueldecrease) * hooked_fuel )
+ if( actor.ammo_fuel >= (time - actor.(weaponentity).hook_time_fueldecrease) * hooked_fuel )
{
- W_DecreaseAmmo(thiswep, actor, (time - actor.hook_time_fueldecrease) * hooked_fuel, weaponentity);
- actor.hook_time_fueldecrease = time;
+ W_DecreaseAmmo(thiswep, actor, (time - actor.(weaponentity).hook_time_fueldecrease) * hooked_fuel, weaponentity);
+ actor.(weaponentity).hook_time_fueldecrease = time;
// decrease next frame again
}
else
{
actor.ammo_fuel = 0;
- actor.hook_state |= HOOK_REMOVING;
+ actor.(weaponentity).hook_state |= HOOK_REMOVING;
W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
}
}
}
else
{
- actor.hook_time_hooked = time;
- actor.hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
+ actor.(weaponentity).hook_time_hooked = time;
+ actor.(weaponentity).hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
}
- actor.hook_state = BITSET(actor.hook_state, HOOK_PULLING, (!PHYS_INPUT_BUTTON_CROUCH(actor) || !autocvar_g_balance_grapplehook_crouchslide));
+ actor.(weaponentity).hook_state = BITSET(actor.(weaponentity).hook_state, HOOK_PULLING, (!PHYS_INPUT_BUTTON_CROUCH(actor) || !autocvar_g_balance_grapplehook_crouchslide));
- if (actor.hook_state & HOOK_FIRING)
+ if (actor.(weaponentity).hook_state & HOOK_FIRING)
{
- if (actor.hook)
- RemoveGrapplingHook(actor);
- FireGrapplingHook(actor);
- actor.hook_state &= ~HOOK_FIRING;
- actor.hook_refire = max(actor.hook_refire, time + autocvar_g_balance_grapplehook_refire * W_WeaponRateFactor(actor));
+ if (actor.(weaponentity).hook)
+ RemoveHook(actor.(weaponentity).hook);
+ FireGrapplingHook(actor, weaponentity);
+ actor.(weaponentity).hook_state &= ~HOOK_FIRING;
+ actor.(weaponentity).hook_refire = max(actor.(weaponentity).hook_refire, time + autocvar_g_balance_grapplehook_refire * W_WeaponRateFactor(actor));
}
- else if (actor.hook_state & HOOK_REMOVING)
+ else if (actor.(weaponentity).hook_state & HOOK_REMOVING)
{
- if (actor.hook)
- RemoveGrapplingHook(actor);
- actor.hook_state &= ~HOOK_REMOVING;
+ if (actor.(weaponentity).hook)
+ RemoveHook(actor.(weaponentity).hook);
+ actor.(weaponentity).hook_state &= ~HOOK_REMOVING;
}
}
METHOD(Hook, wr_setup, void(entity thiswep, entity actor))
{
- actor.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ actor.(weaponentity).hook_state &= ~HOOK_WAITING_FOR_RELEASE;
+ }
}
METHOD(Hook, wr_checkammo1, bool(Hook thiswep, entity actor))
{
if (!thiswep.ammo_factor) return true;
- if(actor.hook)
- return actor.ammo_fuel > 0;
- else
- return actor.ammo_fuel >= WEP_CVAR_PRI(hook, ammo);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(actor.(weaponentity).hook)
+ return actor.ammo_fuel > 0;
+ }
+
+ return actor.ammo_fuel >= WEP_CVAR_PRI(hook, ammo);
}
METHOD(Hook, wr_checkammo2, bool(Hook thiswep, entity actor))
{
}
METHOD(Hook, wr_resetplayer, void(entity thiswep, entity actor))
{
- RemoveGrapplingHook(actor);
- actor.hook_time = 0;
- actor.hook_refire = time;
+ RemoveGrapplingHooks(actor);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ actor.(weaponentity).hook_time = 0;
+ actor.(weaponentity).hook_refire = time;
+ }
}
METHOD(Hook, wr_killmessage, Notification(entity thiswep))
{
if(sf & 1)
{
int myowner = ReadByte();
+ int slot = ReadByte();
this.owner = playerslots[myowner - 1];
this.sv_entnum = myowner;
- if(csqcplayer && myowner == player_localentnum)
- csqcplayer.hook = this;
+ if(myowner == player_localentnum)
+ viewmodels[slot].hook = this;
+ this.cnt = slot;
switch(this.HookType)
{
default:
this.view_ofs = '0 0 0';
}
- RemoveGrapplingHook(this);
+ RemoveGrapplingHooks(this);
Portal_ClearAll(this);
Unfreeze(this);
SetSpectatee(this, NULL);
this.istypefrag = 0;
setthink(this, func_null);
this.nextthink = 0;
- this.hook_time = 0;
this.deadflag = DEAD_NO;
this.crouch = false;
this.revival_time = 0;
this.weaponmodel = "";
for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
+ this.weaponentities[slot].hook_time = 0;
this.weaponentities[slot].weaponname = "";
this.weaponentities[slot] = NULL;
}
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
.entity weaponentity = weaponentities[slot];
- //if(slot == 0)
+ if(slot == 0)
this.(weaponentity).m_switchweapon = w_getbestweapon(this);
- //else
- //this.(weaponentity).m_switchweapon = WEP_Null;
+ else
+ this.(weaponentity).m_switchweapon = WEP_Null;
this.(weaponentity).weaponname = "";
this.(weaponentity).m_switchingweapon = WEP_Null;
this.cnt = -1;
Unfreeze(this);
- RemoveGrapplingHook(this);
+ RemoveGrapplingHooks(this);
// Here, everything has been done that requires this player to be a client.
Ice_Think(ice);
- RemoveGrapplingHook(targ);
+ RemoveGrapplingHooks(targ);
- FOREACH_CLIENT(IS_PLAYER(it) && it.hook.aiment == targ, LAMBDA(RemoveGrapplingHook(it)));
+ FOREACH_CLIENT(IS_PLAYER(it),
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(it.(weaponentity).hook.aiment == targ)
+ RemoveHook(it.(weaponentity).hook);
+ }
+ });
// add waypoint
if(show_waypoint)
WaypointSprite_Kill(targ.waypointsprite_attached);
- FOREACH_CLIENT(IS_PLAYER(it) && it.hook.aiment == targ, LAMBDA(RemoveGrapplingHook(it)));
+ FOREACH_CLIENT(IS_PLAYER(it),
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(it.(weaponentity).hook.aiment == targ)
+ RemoveHook(it.(weaponentity).hook);
+ }
+ });
// remove the ice block
if(targ.iceblock)
attacker_save = attacker;
if(IS_PLAYER(targ))
- if(targ.hook)
- if(targ.hook.aiment)
- if(targ.hook.aiment == attacker)
- RemoveGrapplingHook(targ); // STOP THAT, you parasite!
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(targ.(weaponentity).hook && targ.(weaponentity).hook.aiment == attacker)
+ RemoveHook(targ.(weaponentity).hook);
+ }
+ }
// special rule: gravity bomb does not hit team mates (other than for disconnecting the hook)
if(DEATH_ISWEAPON(deathtype, WEP_HOOK) || DEATH_ISWEAPON(deathtype, WEP_TUBA))
.float hook_length;
-void RemoveGrapplingHook(entity pl)
+void RemoveGrapplingHooks(entity pl)
{
- if(pl.hook == NULL)
- return;
- delete(pl.hook);
- pl.hook = NULL;
if(pl.move_movetype == MOVETYPE_FLY)
set_movetype(pl, MOVETYPE_WALK);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(pl.(weaponentity).hook)
+ {
+ delete(pl.(weaponentity).hook);
+ pl.(weaponentity).hook = NULL;
+ }
+ }
+
//pl.disableclientprediction = false;
}
+void RemoveHook(entity this)
+{
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(this.realowner.(weaponentity).hook == this)
+ this.realowner.(weaponentity).hook = NULL;
+ }
+
+ if(this.realowner.move_movetype == MOVETYPE_FLY)
+ set_movetype(this.realowner, MOVETYPE_WALK);
+ delete(this);
+}
+
void GrapplingHookReset(entity this)
{
- if(this.realowner.hook == this)
- RemoveGrapplingHook(this.owner);
- else // in any case:
- delete(this);
+ RemoveHook(this);
}
void GrapplingHookThink(entity this);
if(sf & 1)
{
WriteByte(MSG_ENTITY, etof(this.realowner));
+ WriteByte(MSG_ENTITY, weaponslot(this.weaponentity_fld));
}
if(sf & 2)
{
{
float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
vector dir, org, end, v0, dv, v, myorg, vs;
- if(this.realowner.hook != this) // how did that happen?
+ .entity weaponentity = this.weaponentity_fld;
+ if(this.realowner.(weaponentity).hook != this) // how did that happen?
{
error("Owner lost the hook!\n");
return;
}
if(LostMovetypeFollow(this) || intermission_running || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || ((this.aiment.flags & FL_PROJECTILE) && this.aiment.classname != "nade"))
{
- RemoveGrapplingHook(this.realowner);
+ RemoveHook(this);
return;
}
if(this.aiment)
this.nextthink = time;
- int s = W_GunAlign(this.realowner, STAT(GUNALIGN, this.realowner));
+ int s = W_GunAlign(this.realowner.(weaponentity), STAT(GUNALIGN, this.realowner));
vs = hook_shotorigin[s];
makevectors(this.realowner.v_angle);
v = v0 = WarpZone_RefSys_TransformVelocity(pull_entity, this, pull_entity.velocity);
// first pull the rope...
- if(this.realowner.hook_state & HOOK_PULLING)
+ if(this.realowner.(weaponentity).hook_state & HOOK_PULLING)
{
newlength = this.hook_length;
newlength = max(newlength - pullspeed * frametime, minlength);
if(pull_entity.move_movetype == MOVETYPE_FLY)
set_movetype(pull_entity, MOVETYPE_WALK);
- if(this.realowner.hook_state & HOOK_RELEASING)
+ if(this.realowner.(weaponentity).hook_state & HOOK_RELEASING)
{
newlength = dist;
this.hook_length = newlength;
if(frozen_pulling && autocvar_g_balance_grapplehook_pull_frozen == 2 && !STAT(FROZEN, this.aiment))
{
- RemoveGrapplingHook(this.realowner);
+ RemoveHook(this);
return;
}
}
this.realowner.pushltime = time + autocvar_g_maxpushtime;
this.realowner.istypefrag = PHYS_INPUT_BUTTON_CHAT(this.realowner);
}
- RemoveGrapplingHook(this.realowner);
+ RemoveHook(this);
}
}
-void FireGrapplingHook(entity actor)
+void FireGrapplingHook(entity actor, .entity weaponentity)
{
entity missile;
vector org;
makevectors(actor.v_angle);
- int s = W_GunAlign(actor, STAT(GUNALIGN, actor));
+ int s = W_GunAlign(actor.(weaponentity), STAT(GUNALIGN, actor));
vs = hook_shotorigin[s];
// UGLY WORKAROUND: play this on CH_WEAPON_B so it can't cut off fire sounds
missile = WarpZone_RefSys_SpawnSameRefSys(actor);
missile.owner = missile.realowner = actor;
- actor.hook = missile;
+ actor.(weaponentity).hook = missile;
+ missile.weaponentity_fld = weaponentity;
missile.reset = GrapplingHookReset;
missile.classname = "grapplinghook";
missile.flags = FL_PROJECTILE;
// Wazat's grappling hook
.entity hook;
-void RemoveGrapplingHook(entity pl);
+void RemoveGrapplingHooks(entity pl);
+void RemoveHook(entity this);
// (note: you can change the hook impulse #'s to whatever you please)
.float hook_time;
if(this.classname == "nade")
return false; // no checks here
else if(this.classname == "grapplinghook")
- RemoveGrapplingHook(this.realowner);
+ RemoveHook(this);
else if(this.classname == "spike")
{
W_Crylink_Dequeue(this);
excess = M_ARGV(4, float);
Weapon wep = this.(weaponentity).m_weapon;
- /*for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
.entity weaponentity = weaponentities[slot];
wep.wr_playerdeath(wep, this, weaponentity);
- }*/
- wep.wr_playerdeath(wep, this, weaponentity);
+ }
- RemoveGrapplingHook(this);
+ RemoveGrapplingHooks(this);
Portal_ClearAllLater(this);
if(it != o || time >= this.portal_activatetime)
Portal_Think_TryTeleportPlayer(this, it, g);
- if(it.hook)
- Portal_Think_TryTeleportPlayer(this, it.hook, g);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(it.(weaponentity).hook)
+ Portal_Think_TryTeleportPlayer(this, it.(weaponentity).hook, g);
+ }
));
this.solid = SOLID_TRIGGER;
this.aiment = o;
{
// check for falling damage
float velocity_len = vlen(this.velocity);
- if(!this.hook.state)
+ bool have_hook = false;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(this.(weaponentity).hook && this.(weaponentity).hook.state)
+ {
+ have_hook = true;
+ break;
+ }
+ }
+ if(!have_hook)
{
float dm = vlen(this.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
if (IS_DEAD(this))
return ret;
}
-..entity weaponentity_fld;
.float m_alpha;
.string w_weaponname;
.int w_dmg;
}
ATTACK_FINISHED(actor, slot) = ATTACK_FINISHED(actor, slot) + attacktime * W_WeaponRateFactor(actor);
}
- actor.(weaponentity).bulletcounter += 1;
+ this.bulletcounter += 1;
// dprint("attack finished ", ftos(ATTACK_FINISHED(actor, slot)), "\n");
}
float weaponswapping;
entity weapon_dropevent_item;
+..entity weaponentity_fld;
+
void CL_SpawnWeaponentity(entity e, .entity weaponentity);
vector CL_Weapon_GetShotOrg(float wpn);