From ddc62cfa14598f893f3986906f6b05a2d33fcb8c Mon Sep 17 00:00:00 2001 From: kitsune Date: Mon, 3 Nov 2025 03:34:02 +0100 Subject: [PATCH 1/4] Fixes: Weapons: Revised radiation volume. --- .../server/swarm/asw_radiation_volume.cpp | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/game/server/swarm/asw_radiation_volume.cpp b/src/game/server/swarm/asw_radiation_volume.cpp index cd5db90b8..0704774dc 100644 --- a/src/game/server/swarm/asw_radiation_volume.cpp +++ b/src/game/server/swarm/asw_radiation_volume.cpp @@ -44,7 +44,7 @@ void CASW_Radiation_Volume::Spawn( void ) AddEffects(EF_NODRAW); SetSolid( SOLID_BBOX ); float boxWidth = m_flBoxWidth; - UTIL_SetSize(this, Vector(-boxWidth,-boxWidth,0),Vector(boxWidth,boxWidth,boxWidth * 2)); + UTIL_SetSize( this, Vector( -boxWidth, -boxWidth, 0 ), Vector( boxWidth, boxWidth, boxWidth ) ); SetCollisionGroup(ASW_COLLISION_GROUP_PASSABLE); AddSolidFlags(FSOLID_TRIGGER | FSOLID_NOT_SOLID); SetTouch( &CASW_Radiation_Volume::RadTouch ); @@ -61,25 +61,52 @@ bool CASW_Radiation_Volume::IsValidRadTarget( CBaseEntity *pOther ) return pOther->IsNPC(); } -void CASW_Radiation_Volume::RadTouch( CBaseEntity *pOther ) +void CASW_Radiation_Volume::RadTouch( CBaseEntity* pOther ) { // if other is a valid entity to radiate, add it to our list - if (IsValidRadTarget(pOther) && m_hRadTouching.Find(pOther) == m_hRadTouching.InvalidIndex()) + if ( !IsValidRadTarget( pOther ) ) + return; + + // Treat m_flBoxWidth as radius: + float flRadius = m_flBoxWidth; + + // If entity has a collision prop, compute nearest point and test 3D distance (sphere) + if ( pOther->CollisionProp() ) + { + Vector vecNearest; + pOther->CollisionProp()->CalcNearestPoint( GetAbsOrigin(), &vecNearest ); + + Vector vecDelta = vecNearest - GetAbsOrigin(); + if ( vecDelta.Length() > flRadius ) + return; // outside the sphere + } + + if ( m_hRadTouching.Find( pOther ) == m_hRadTouching.InvalidIndex() ) { - m_hRadTouching.AddToTail(pOther); - if (GetNextThink() == TICK_NEVER_THINK) + m_hRadTouching.AddToTail( pOther ); + if ( GetNextThink() == TICK_NEVER_THINK ) SetNextThink( gpGlobals->curtime ); } } -bool CASW_Radiation_Volume::RadTouching(CBaseEntity *pEnt) +bool CASW_Radiation_Volume::RadTouching( CBaseEntity* pEnt ) { - if (!pEnt || !pEnt->CollisionProp() || !CollisionProp()) + if ( !pEnt || !pEnt->CollisionProp() ) return false; + // Treat m_flBoxWidth as radius: + float flRadius = m_flBoxWidth; + + // nearest point on the entity to our center Vector vecNearest; pEnt->CollisionProp()->CalcNearestPoint( GetAbsOrigin(), &vecNearest ); - return CollisionProp()->IsPointInBounds(vecNearest); + + // Sphere test (3D) + Vector vecDelta = vecNearest - GetAbsOrigin(); + if ( vecDelta.Length() > flRadius ) + return false; // outside the sphere + + return true; } void CASW_Radiation_Volume::RadHurt(CBaseEntity *pEnt) From f8e20bd4c3520b1abae7312694c17e45c3b14692 Mon Sep 17 00:00:00 2001 From: kitsune Date: Tue, 4 Nov 2025 07:41:56 +0100 Subject: [PATCH 2/4] update --- .../server/swarm/asw_radiation_volume.cpp | 89 ++++++++++++++----- 1 file changed, 69 insertions(+), 20 deletions(-) diff --git a/src/game/server/swarm/asw_radiation_volume.cpp b/src/game/server/swarm/asw_radiation_volume.cpp index 0704774dc..f60ece6cb 100644 --- a/src/game/server/swarm/asw_radiation_volume.cpp +++ b/src/game/server/swarm/asw_radiation_volume.cpp @@ -67,20 +67,46 @@ void CASW_Radiation_Volume::RadTouch( CBaseEntity* pOther ) if ( !IsValidRadTarget( pOther ) ) return; - // Treat m_flBoxWidth as radius: - float flRadius = m_flBoxWidth; + // m_flBoxWidth used as radius: + const float flRadius = m_flBoxWidth; + const float flRadiusSqr = flRadius * flRadius; + + const Vector vecCenter = GetAbsOrigin(); + CCollisionProperty* pOtherColl = pOther->CollisionProp(); // cache + CCollisionProperty* pVolColl = CollisionProp(); // cache + if ( !pVolColl ) + return; - // If entity has a collision prop, compute nearest point and test 3D distance (sphere) - if ( pOther->CollisionProp() ) + // compute the nearest point on the other entity to our center (robust for large NPCs) + Vector vecNearest; + if ( pOtherColl ) + pOtherColl->CalcNearestPoint( vecCenter, &vecNearest ); + else + vecNearest = pOther->WorldSpaceCenter(); + + // If other is a marine, use CYLINDER test: + // - horizontal (XY) distance < radius + // - AND the nearest point must be within our cuboid bounds (so Z is constrained by the volume) + if ( pOther->Classify() == CLASS_ASW_MARINE ) { - Vector vecNearest; - pOther->CollisionProp()->CalcNearestPoint( GetAbsOrigin(), &vecNearest ); - - Vector vecDelta = vecNearest - GetAbsOrigin(); - if ( vecDelta.Length() > flRadius ) - return; // outside the sphere + // must be within our cuboid in Z (IsPointInBounds) and within horizontal radius + if ( pVolColl->IsPointInBounds( vecNearest ) ) + { + // horizontal delta (XY) + Vector vecDelta = vecNearest - vecCenter; + // horizontal distance squared check (circle) + if ( ( vecDelta.x * vecDelta.x + vecDelta.y * vecDelta.y ) >= flRadiusSqr ) + return; + } + } + else + { + // aliens: full cuboid check only + if ( !pVolColl->IsPointInBounds( vecNearest ) ) + return; } + // avoid duplicates if ( m_hRadTouching.Find( pOther ) == m_hRadTouching.InvalidIndex() ) { m_hRadTouching.AddToTail( pOther ); @@ -91,22 +117,45 @@ void CASW_Radiation_Volume::RadTouch( CBaseEntity* pOther ) bool CASW_Radiation_Volume::RadTouching( CBaseEntity* pEnt ) { - if ( !pEnt || !pEnt->CollisionProp() ) + if ( !pEnt ) return false; - // Treat m_flBoxWidth as radius: - float flRadius = m_flBoxWidth; + // m_flBoxWidth used as radius: + const float flRadius = m_flBoxWidth; + const float flRadiusSqr = flRadius * flRadius; + + const Vector vecCenter = GetAbsOrigin(); + CCollisionProperty* pEntColl = pEnt->CollisionProp(); // cache + CCollisionProperty* pVolColl = CollisionProp(); // cache + if ( !pVolColl ) + return false; - // nearest point on the entity to our center + // compute the nearest point on the other entity to our center (robust for large NPCs) Vector vecNearest; - pEnt->CollisionProp()->CalcNearestPoint( GetAbsOrigin(), &vecNearest ); + if ( pEntColl ) + pEntColl->CalcNearestPoint( vecCenter, &vecNearest ); + else + vecNearest = pEnt->WorldSpaceCenter(); + + // If other is a marine, use CYLINDER test: + // - horizontal (XY) distance < radius + // - AND the nearest point must be within our cuboid bounds (so Z is constrained by the volume) + if ( pEnt->Classify() == CLASS_ASW_MARINE ) + { + // must be inside vertical bounds (cuboid) + if ( !pVolColl->IsPointInBounds( vecNearest ) ) + return false; - // Sphere test (3D) - Vector vecDelta = vecNearest - GetAbsOrigin(); - if ( vecDelta.Length() > flRadius ) - return false; // outside the sphere + // horizontal delta (XY) + Vector vecDelta = vecNearest - vecCenter; + // horizontal distance squared check (circle) + if ( ( vecDelta.x * vecDelta.x + vecDelta.y * vecDelta.y ) >= flRadiusSqr ) + return false; - return true; + return true; + } + // aliens: full cuboid + return pVolColl->IsPointInBounds( vecNearest ); } void CASW_Radiation_Volume::RadHurt(CBaseEntity *pEnt) From f7e18685a1e871466122e2608e5461fc7e997b5f Mon Sep 17 00:00:00 2001 From: kitsune Date: Tue, 4 Nov 2025 21:09:47 +0100 Subject: [PATCH 3/4] refactor --- .../server/swarm/asw_radiation_volume.cpp | 82 ++++++------------- src/game/server/swarm/asw_radiation_volume.h | 2 + 2 files changed, 26 insertions(+), 58 deletions(-) diff --git a/src/game/server/swarm/asw_radiation_volume.cpp b/src/game/server/swarm/asw_radiation_volume.cpp index f60ece6cb..b7b96ab44 100644 --- a/src/game/server/swarm/asw_radiation_volume.cpp +++ b/src/game/server/swarm/asw_radiation_volume.cpp @@ -61,61 +61,8 @@ bool CASW_Radiation_Volume::IsValidRadTarget( CBaseEntity *pOther ) return pOther->IsNPC(); } -void CASW_Radiation_Volume::RadTouch( CBaseEntity* pOther ) -{ - // if other is a valid entity to radiate, add it to our list - if ( !IsValidRadTarget( pOther ) ) - return; - - // m_flBoxWidth used as radius: - const float flRadius = m_flBoxWidth; - const float flRadiusSqr = flRadius * flRadius; - - const Vector vecCenter = GetAbsOrigin(); - CCollisionProperty* pOtherColl = pOther->CollisionProp(); // cache - CCollisionProperty* pVolColl = CollisionProp(); // cache - if ( !pVolColl ) - return; - - // compute the nearest point on the other entity to our center (robust for large NPCs) - Vector vecNearest; - if ( pOtherColl ) - pOtherColl->CalcNearestPoint( vecCenter, &vecNearest ); - else - vecNearest = pOther->WorldSpaceCenter(); - - // If other is a marine, use CYLINDER test: - // - horizontal (XY) distance < radius - // - AND the nearest point must be within our cuboid bounds (so Z is constrained by the volume) - if ( pOther->Classify() == CLASS_ASW_MARINE ) - { - // must be within our cuboid in Z (IsPointInBounds) and within horizontal radius - if ( pVolColl->IsPointInBounds( vecNearest ) ) - { - // horizontal delta (XY) - Vector vecDelta = vecNearest - vecCenter; - // horizontal distance squared check (circle) - if ( ( vecDelta.x * vecDelta.x + vecDelta.y * vecDelta.y ) >= flRadiusSqr ) - return; - } - } - else - { - // aliens: full cuboid check only - if ( !pVolColl->IsPointInBounds( vecNearest ) ) - return; - } - - // avoid duplicates - if ( m_hRadTouching.Find( pOther ) == m_hRadTouching.InvalidIndex() ) - { - m_hRadTouching.AddToTail( pOther ); - if ( GetNextThink() == TICK_NEVER_THINK ) - SetNextThink( gpGlobals->curtime ); - } -} - -bool CASW_Radiation_Volume::RadTouching( CBaseEntity* pEnt ) +// Helper centralizing detection logic used by RadTouch and RadTouching +bool CASW_Radiation_Volume::IsInRadiationVolume( CBaseEntity *pEnt ) { if ( !pEnt ) return false; @@ -125,8 +72,8 @@ bool CASW_Radiation_Volume::RadTouching( CBaseEntity* pEnt ) const float flRadiusSqr = flRadius * flRadius; const Vector vecCenter = GetAbsOrigin(); - CCollisionProperty* pEntColl = pEnt->CollisionProp(); // cache - CCollisionProperty* pVolColl = CollisionProp(); // cache + CCollisionProperty* pEntColl = pEnt->CollisionProp(); + CCollisionProperty* pVolColl = CollisionProp(); if ( !pVolColl ) return false; @@ -158,6 +105,25 @@ bool CASW_Radiation_Volume::RadTouching( CBaseEntity* pEnt ) return pVolColl->IsPointInBounds( vecNearest ); } +void CASW_Radiation_Volume::RadTouch( CBaseEntity* pOther ) +{ + // if other is a valid entity to radiate, add it to our list + if ( !IsValidRadTarget( pOther ) + || m_hRadTouching.Find( pOther ) != m_hRadTouching.InvalidIndex() // avoid duplicates + || !IsInRadiationVolume( pOther ) ) + return; + + m_hRadTouching.AddToTail( pOther ); + if ( GetNextThink() == TICK_NEVER_THINK ) + SetNextThink( gpGlobals->curtime ); +} + +bool CASW_Radiation_Volume::RadTouching( CBaseEntity* pEnt ) +{ + // simply reuse centralized detection + return IsInRadiationVolume( pEnt ); +} + void CASW_Radiation_Volume::RadHurt(CBaseEntity *pEnt) { if (!pEnt) @@ -166,7 +132,7 @@ void CASW_Radiation_Volume::RadHurt(CBaseEntity *pEnt) int iDamageType = DMG_RADIATION; CBaseEntity *pAttacker = this; - if (m_hCreator.Get() && pEnt->Classify() != CLASS_ASW_MARINE) // don't deal friendly fire damage from rad barrels + if (m_hCreator.Get() && pEnt->Classify() != CLASS_ASW_MARINE) // don't deal friendly fire damage from rad barrels pAttacker = m_hCreator.Get(); CBaseEntity *pWeapon = NULL; diff --git a/src/game/server/swarm/asw_radiation_volume.h b/src/game/server/swarm/asw_radiation_volume.h index 561b92d14..86611b082 100644 --- a/src/game/server/swarm/asw_radiation_volume.h +++ b/src/game/server/swarm/asw_radiation_volume.h @@ -13,6 +13,8 @@ class CASW_Radiation_Volume : public CBaseEntity void RadHurt(CBaseEntity *pEnt); bool RadTouching(CBaseEntity *pEnt); bool IsValidRadTarget( CBaseEntity *pOther ); + // helper that centralizes the collision/volume checks used by RadTouch and RadTouching + bool IsInRadiationVolume( CBaseEntity *pEnt ); DECLARE_DATADESC(); CUtlVector m_hRadTouching; From a0f01b0782e733f30f05a7e5396afe663fbc0d37 Mon Sep 17 00:00:00 2001 From: kitsune Date: Tue, 4 Nov 2025 21:10:59 +0100 Subject: [PATCH 4/4] fix --- src/game/server/swarm/asw_radiation_volume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/server/swarm/asw_radiation_volume.cpp b/src/game/server/swarm/asw_radiation_volume.cpp index b7b96ab44..97c96aede 100644 --- a/src/game/server/swarm/asw_radiation_volume.cpp +++ b/src/game/server/swarm/asw_radiation_volume.cpp @@ -44,7 +44,7 @@ void CASW_Radiation_Volume::Spawn( void ) AddEffects(EF_NODRAW); SetSolid( SOLID_BBOX ); float boxWidth = m_flBoxWidth; - UTIL_SetSize( this, Vector( -boxWidth, -boxWidth, 0 ), Vector( boxWidth, boxWidth, boxWidth ) ); + UTIL_SetSize( this, Vector( -boxWidth, -boxWidth, 0 ), Vector( boxWidth, boxWidth, boxWidth * 2 ) ); SetCollisionGroup(ASW_COLLISION_GROUP_PASSABLE); AddSolidFlags(FSOLID_TRIGGER | FSOLID_NOT_SOLID); SetTouch( &CASW_Radiation_Volume::RadTouch );