From ceb39e77a64562548ab97a7087461e33b8379d4a Mon Sep 17 00:00:00 2001 From: terencehill Date: Sat, 17 Dec 2022 02:08:23 +0100 Subject: [PATCH] Optimize damageeffects code: when a hitscan weapon hits a surface avoid executing a client-side traceline to check where's the hit point since this point is already known server-side. --- qcsrc/common/effects/qc/damageeffects.qc | 19 ++++++++++++++----- qcsrc/common/mutators/mutator/nades/nades.qc | 4 ++-- .../common/vehicles/vehicle/raptor_weapons.qc | 2 +- qcsrc/common/weapons/weapon/seeker.qc | 4 ++-- qcsrc/common/weapons/weapon/shockwave.qc | 1 + qcsrc/server/damage.qc | 4 ++-- qcsrc/server/damage.qh | 2 +- qcsrc/server/weapons/tracing.qc | 6 +++--- 8 files changed, 26 insertions(+), 16 deletions(-) diff --git a/qcsrc/common/effects/qc/damageeffects.qc b/qcsrc/common/effects/qc/damageeffects.qc index 20a335b6b..cb58a055c 100644 --- a/qcsrc/common/effects/qc/damageeffects.qc +++ b/qcsrc/common/effects/qc/damageeffects.qc @@ -18,7 +18,7 @@ bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf) return true; } -void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner) +void Damage_DamageInfo(vector org, bool is_solid_hit, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner) { // TODO maybe call this from non-edgedamage too? // TODO maybe make the client do the particle effects for the weapons and the impact sounds using this info? @@ -39,6 +39,8 @@ void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad e.dmg_force = vlen(force); e.velocity = force; e.species = bloodtype; + if(is_solid_hit) + e.species |= 0x80; Net_LinkEntity(e, false, 0.2, Damage_DamageInfo_SendEntity); } @@ -193,6 +195,8 @@ NET_HANDLE(ENT_CLIENT_DAMAGEINFO, bool isNew) edge = ReadByte(); force = ReadVector(); species = ReadByte(); + bool is_solid_hit = (species & 0x80); + species = (species & 0x7F); return = true; @@ -396,11 +400,16 @@ NET_HANDLE(ENT_CLIENT_DAMAGEINFO, bool isNew) w_random = prandom(); vector force_dir = normalize(force); - traceline(w_org - force_dir * 16, w_org + force_dir * 16, MOVE_NOMONSTERS, NULL); - if(trace_fraction < 1 && !(hitwep.spawnflags & WEP_TYPE_HITSCAN)) - w_backoff = trace_plane_normal; - else + if (is_solid_hit) // traceline not needed w_backoff = -force_dir; + else + { + traceline(w_org - force_dir * 16, w_org + force_dir * 16, MOVE_NOMONSTERS, NULL); + if(trace_fraction < 1 && !(hitwep.spawnflags & WEP_TYPE_HITSCAN)) + w_backoff = trace_plane_normal; + else + w_backoff = -force_dir; + } setorigin(this, w_org + w_backoff * 2); // for sound() calls if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)) diff --git a/qcsrc/common/mutators/mutator/nades/nades.qc b/qcsrc/common/mutators/mutator/nades/nades.qc index 1707e168b..4deecc492 100644 --- a/qcsrc/common/mutators/mutator/nades/nades.qc +++ b/qcsrc/common/mutators/mutator/nades/nades.qc @@ -395,7 +395,7 @@ void nade_ice_think(entity this) RadiusDamage(this, this.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, DMG_NOWEP, this.enemy); - Damage_DamageInfo(this.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, + Damage_DamageInfo(this.origin, false, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this); } delete(this); @@ -749,7 +749,7 @@ void nade_boom(entity this) { RadiusDamage(this, this.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, this, NULL, autocvar_g_nades_nade_force, this.projectiledeathtype, DMG_NOWEP, this.enemy); - Damage_DamageInfo(this.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this); + Damage_DamageInfo(this.origin, false, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, this.projectiledeathtype, 0, this); } if(this.takedamage) diff --git a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc index dc219f571..30c826c50 100644 --- a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc @@ -121,7 +121,7 @@ void raptor_bomb_burst(entity this) entity bomblet; float i; - Damage_DamageInfo(this.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT.m_id, 0, this); + Damage_DamageInfo(this.origin, false, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT.m_id, 0, this); for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i) { diff --git a/qcsrc/common/weapons/weapon/seeker.qc b/qcsrc/common/weapons/weapon/seeker.qc index bf57fb9c1..e4b767451 100644 --- a/qcsrc/common/weapons/weapon/seeker.qc +++ b/qcsrc/common/weapons/weapon/seeker.qc @@ -406,7 +406,7 @@ void W_Seeker_Tag_Explode(entity this) { //if(other==this.realowner) // return; - Damage_DamageInfo(this.origin, 0, 0, 0, this.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE, 0, this); + Damage_DamageInfo(this.origin, false, 0, 0, 0, this.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE, 0, this); delete(this); } @@ -434,7 +434,7 @@ void W_Seeker_Tag_Touch(entity this, entity toucher) te_knightspike(org2); this.event_damage = func_null; - Damage_DamageInfo(this.origin, 0, 0, 0, this.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE | HITTYPE_SECONDARY, toucher.species, this); + Damage_DamageInfo(this.origin, false, 0, 0, 0, this.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE | HITTYPE_SECONDARY, toucher.species, this); if(toucher.takedamage == DAMAGE_AIM && !IS_DEAD(toucher)) { diff --git a/qcsrc/common/weapons/weapon/shockwave.qc b/qcsrc/common/weapons/weapon/shockwave.qc index 7863de55e..f91544d76 100644 --- a/qcsrc/common/weapons/weapon/shockwave.qc +++ b/qcsrc/common/weapons/weapon/shockwave.qc @@ -279,6 +279,7 @@ void W_Shockwave_Attack(Weapon thiswep, entity actor, .entity weaponentity) W_Shockwave_Send(actor); Damage_DamageInfo( attack_hitpos, + trace_ent && trace_ent.solid == SOLID_BSP, WEP_CVAR(shockwave, blast_splash_damage), WEP_CVAR(shockwave, blast_splash_edgedamage), WEP_CVAR(shockwave, blast_splash_radius), diff --git a/qcsrc/server/damage.qc b/qcsrc/server/damage.qc index d93d00bf5..296a7b107 100644 --- a/qcsrc/server/damage.qc +++ b/qcsrc/server/damage.qc @@ -902,9 +902,9 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in else force = normalize(force); if(forceintensity >= 0) - Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker); + Damage_DamageInfo(inflictororigin, false, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker); else - Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker); + Damage_DamageInfo(inflictororigin, false, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker); } stat_damagedone = 0; diff --git a/qcsrc/server/damage.qh b/qcsrc/server/damage.qh index a1dadc1a2..cc4dd30a5 100644 --- a/qcsrc/server/damage.qh +++ b/qcsrc/server/damage.qh @@ -41,7 +41,7 @@ float autocvar_g_frozen_force; bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf); -void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner); +void Damage_DamageInfo(vector org, bool is_solid_hit, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner); float checkrules_firstblood; diff --git a/qcsrc/server/weapons/tracing.qc b/qcsrc/server/weapons/tracing.qc index 686634c7a..c515d8fc9 100644 --- a/qcsrc/server/weapons/tracing.qc +++ b/qcsrc/server/weapons/tracing.qc @@ -256,7 +256,7 @@ void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector } if(trace_ent.solid == SOLID_BSP || trace_ent.solid == SOLID_SLIDEBOX) - Damage_DamageInfo(trace_endpos, bdamage, 0, 0, force, deathtype, trace_ent.species, this); + Damage_DamageInfo(trace_endpos, (trace_ent.solid == SOLID_BSP), bdamage, 0, 0, force, deathtype, trace_ent.species, this); // if it is NULL we can't hurt it so stop now if (trace_ent == NULL || trace_fraction == 1) @@ -417,7 +417,7 @@ void fireBullet_antilag(entity this, .entity weaponentity, vector start, vector is_weapclip = true; if(!hit || hit.solid == SOLID_BSP || hit.solid == SOLID_SLIDEBOX) - Damage_DamageInfo(start, damage * damage_fraction, 0, 0, max(1, force) * dir * damage_fraction, dtype, hit.species, this); + Damage_DamageInfo(start, (hit && hit.solid == SOLID_BSP), damage * damage_fraction, 0, 0, max(1, force) * dir * damage_fraction, dtype, hit.species, this); if (hit && hit != WarpZone_trace_forent && hit != fireBullet_last_hit) // Avoid self-damage (except after going through a warp); avoid hitting the same entity twice (engine bug). { @@ -486,7 +486,7 @@ void fireBullet_antilag(entity this, .entity weaponentity, vector start, vector start = trace_endpos; if(hit.solid == SOLID_BSP) - Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -damage_fraction, dtype, 0, this); + Damage_DamageInfo(start, true, 0, 0, 0, max(1, force) * normalize(dir) * -damage_fraction, dtype, 0, this); } if(headshot) -- 2.39.2