From: Mario Date: Thu, 29 Sep 2016 08:54:53 +0000 (+1000) Subject: Attempt to make hook depend on weaponentity instead of the player X-Git-Tag: xonotic-v0.8.2~326^2~88 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=f23e93047012043fe9c7c3bf533546c364b18bde;p=xonotic%2Fxonotic-data.pk3dir.git Attempt to make hook depend on weaponentity instead of the player --- diff --git a/qcsrc/common/mutators/mutator/breakablehook/sv_breakablehook.qc b/qcsrc/common/mutators/mutator/breakablehook/sv_breakablehook.qc index fdb0dc38d..dfde6ed73 100644 --- a/qcsrc/common/mutators/mutator/breakablehook/sv_breakablehook.qc +++ b/qcsrc/common/mutators/mutator/breakablehook/sv_breakablehook.qc @@ -23,7 +23,7 @@ MUTATOR_HOOKFUNCTION(breakablehook, PlayerDamage_Calculate) 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 } } diff --git a/qcsrc/common/mutators/mutator/nades/nades.qc b/qcsrc/common/mutators/mutator/nades/nades.qc index 02760045c..d34874598 100644 --- a/qcsrc/common/mutators/mutator/nades/nades.qc +++ b/qcsrc/common/mutators/mutator/nades/nades.qc @@ -736,7 +736,7 @@ void nade_boom(entity this) IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this, { - RemoveGrapplingHook(it.realowner); + RemoveHook(it); }); delete(this); @@ -785,7 +785,7 @@ void nade_touch(entity this, entity toucher) { IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this, { - RemoveGrapplingHook(it.realowner); + RemoveHook(it); }); delete(this); return; diff --git a/qcsrc/common/physics/player.qc b/qcsrc/common/physics/player.qc index 4eb527d62..5978fb658 100644 --- a/qcsrc/common/physics/player.qc +++ b/qcsrc/common/physics/player.qc @@ -89,8 +89,15 @@ void PM_ClientMovement_UpdateStatus(entity this) // 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) @@ -600,7 +607,12 @@ void PM_check_hitground(entity this) 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); diff --git a/qcsrc/common/triggers/trigger/teleport.qc b/qcsrc/common/triggers/trigger/teleport.qc index c3de65460..1fabc80a5 100644 --- a/qcsrc/common/triggers/trigger/teleport.qc +++ b/qcsrc/common/triggers/trigger/teleport.qc @@ -43,7 +43,7 @@ void Teleport_Touch(entity this, entity toucher) #ifdef SVQC if(IS_PLAYER(toucher)) - RemoveGrapplingHook(toucher); + RemoveGrapplingHooks(toucher); #endif entity e; diff --git a/qcsrc/common/vehicles/sv_vehicles.qc b/qcsrc/common/vehicles/sv_vehicles.qc index bcb063186..75d2f4635 100644 --- a/qcsrc/common/vehicles/sv_vehicles.qc +++ b/qcsrc/common/vehicles/sv_vehicles.qc @@ -947,7 +947,7 @@ void vehicles_enter(entity pl, entity veh) } else return; - RemoveGrapplingHook(pl); + RemoveGrapplingHooks(pl); veh.vehicle_ammo1 = 0; veh.vehicle_ammo2 = 0; @@ -1109,7 +1109,15 @@ void vehicles_spawn(entity this) 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); diff --git a/qcsrc/common/vehicles/vehicle/bumblebee.qc b/qcsrc/common/vehicles/vehicle/bumblebee.qc index 4f74c8636..7bc10b4ec 100644 --- a/qcsrc/common/vehicles/vehicle/bumblebee.qc +++ b/qcsrc/common/vehicles/vehicle/bumblebee.qc @@ -309,7 +309,7 @@ bool bumblebee_gunner_enter(entity this, entity player) player.vehicle_energy = vehic.vehicle_energy; UNSET_ONGROUND(player); - RemoveGrapplingHook(player); + RemoveGrapplingHooks(player); for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { diff --git a/qcsrc/common/weapons/all.qc b/qcsrc/common/weapons/all.qc index 99b232730..d2acab1a0 100644 --- a/qcsrc/common/weapons/all.qc +++ b/qcsrc/common/weapons/all.qc @@ -523,7 +523,9 @@ void CL_WeaponEntity_SetModel(entity this, string name, bool _anim) 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; diff --git a/qcsrc/common/weapons/all.qh b/qcsrc/common/weapons/all.qh index 90cbe28db..12e26ac4e 100644 --- a/qcsrc/common/weapons/all.qh +++ b/qcsrc/common/weapons/all.qh @@ -339,6 +339,8 @@ vector weaponentity_glowmod(Weapon wep, entity actor, int c) entity gunaligns[5]; #endif +.int m_gunalign; + //.int weapon; // current weapon .string weaponname; // name of .weapon diff --git a/qcsrc/common/weapons/weapon/hook.qc b/qcsrc/common/weapons/weapon/hook.qc index 2b322f760..c24db6583 100644 --- a/qcsrc/common/weapons/weapon/hook.qc +++ b/qcsrc/common/weapons/weapon/hook.qc @@ -191,19 +191,19 @@ void W_Hook_Attack2(Weapon thiswep, entity actor, .entity weaponentity) 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) @@ -215,42 +215,42 @@ METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity, } } - 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); } } @@ -259,38 +259,46 @@ METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity 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)) { @@ -299,9 +307,13 @@ 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)) { @@ -510,10 +522,12 @@ NET_HANDLE(ENT_CLIENT_HOOK, bool bIsNew) 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: diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index ddb23f0b1..d6805263c 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -257,7 +257,7 @@ void PutObserverInServer(entity this) this.view_ofs = '0 0 0'; } - RemoveGrapplingHook(this); + RemoveGrapplingHooks(this); Portal_ClearAll(this); Unfreeze(this); SetSpectatee(this, NULL); @@ -334,7 +334,6 @@ void PutObserverInServer(entity this) 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; @@ -346,6 +345,7 @@ void PutObserverInServer(entity this) this.weaponmodel = ""; for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { + this.weaponentities[slot].hook_time = 0; this.weaponentities[slot].weaponname = ""; this.weaponentities[slot] = NULL; } @@ -695,10 +695,10 @@ void PutClientInServer(entity this) 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; @@ -1254,7 +1254,7 @@ void ClientDisconnect(entity this) Unfreeze(this); - RemoveGrapplingHook(this); + RemoveGrapplingHooks(this); // Here, everything has been done that requires this player to be a client. diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index 6851f7cdf..fd8e89c9f 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -561,9 +561,17 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo 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) @@ -590,7 +598,15 @@ void Unfreeze (entity targ) 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) @@ -616,10 +632,14 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d 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)) diff --git a/qcsrc/server/g_hook.qc b/qcsrc/server/g_hook.qc index 92d6ccac4..636e8c6aa 100644 --- a/qcsrc/server/g_hook.qc +++ b/qcsrc/server/g_hook.qc @@ -70,24 +70,41 @@ And you should be done! .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); @@ -116,6 +133,7 @@ bool GrapplingHookSend(entity this, entity to, int sf) if(sf & 1) { WriteByte(MSG_ENTITY, etof(this.realowner)); + WriteByte(MSG_ENTITY, weaponslot(this.weaponentity_fld)); } if(sf & 2) { @@ -138,14 +156,15 @@ void GrapplingHookThink(entity this) { 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) @@ -153,7 +172,7 @@ void GrapplingHookThink(entity this) 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); @@ -205,7 +224,7 @@ void GrapplingHookThink(entity this) 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); @@ -223,7 +242,7 @@ void GrapplingHookThink(entity this) 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; @@ -265,7 +284,7 @@ void GrapplingHookThink(entity this) if(frozen_pulling && autocvar_g_balance_grapplehook_pull_frozen == 2 && !STAT(FROZEN, this.aiment)) { - RemoveGrapplingHook(this.realowner); + RemoveHook(this); return; } } @@ -337,11 +356,11 @@ void GrapplingHook_Damage(entity this, entity inflictor, entity attacker, float 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; @@ -352,7 +371,7 @@ void FireGrapplingHook(entity actor) 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 @@ -366,7 +385,8 @@ void FireGrapplingHook(entity actor) 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; diff --git a/qcsrc/server/g_hook.qh b/qcsrc/server/g_hook.qh index 900c23d36..719bf5b60 100644 --- a/qcsrc/server/g_hook.qh +++ b/qcsrc/server/g_hook.qh @@ -2,7 +2,8 @@ // 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; diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index d38eedaf3..2914ca2de 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -1076,7 +1076,7 @@ bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher 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); diff --git a/qcsrc/server/player.qc b/qcsrc/server/player.qc index 6bfee14b2..8b44e39ca 100644 --- a/qcsrc/server/player.qc +++ b/qcsrc/server/player.qc @@ -563,14 +563,13 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage, 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); diff --git a/qcsrc/server/portals.qc b/qcsrc/server/portals.qc index 12083e423..b41c53bbc 100644 --- a/qcsrc/server/portals.qc +++ b/qcsrc/server/portals.qc @@ -481,8 +481,12 @@ void Portal_Think(entity 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; diff --git a/qcsrc/server/sv_main.qc b/qcsrc/server/sv_main.qc index ea11ea36a..ccc309be6 100644 --- a/qcsrc/server/sv_main.qc +++ b/qcsrc/server/sv_main.qc @@ -99,7 +99,17 @@ void CreatureFrame_FallDamage(entity this) { // 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)) diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc index 458383500..0dffe0289 100644 --- a/qcsrc/server/weapons/weaponsystem.qc +++ b/qcsrc/server/weapons/weaponsystem.qc @@ -60,7 +60,6 @@ vector CL_Weapon_GetShotOrg(int wpn) return ret; } -..entity weaponentity_fld; .float m_alpha; .string w_weaponname; .int w_dmg; @@ -317,7 +316,7 @@ void weapon_prepareattack_do(entity actor, .entity weaponentity, bool secondary, } 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"); } diff --git a/qcsrc/server/weapons/weaponsystem.qh b/qcsrc/server/weapons/weaponsystem.qh index bdc261d8e..389a52bcc 100644 --- a/qcsrc/server/weapons/weaponsystem.qh +++ b/qcsrc/server/weapons/weaponsystem.qh @@ -4,6 +4,8 @@ float internalteam; float weaponswapping; entity weapon_dropevent_item; +..entity weaponentity_fld; + void CL_SpawnWeaponentity(entity e, .entity weaponentity); vector CL_Weapon_GetShotOrg(float wpn);