The problem with the HurtRadius function is the poor support for small radii. To overcome this problem, I wrote a function that checks against the actual collision cylinder:
Code:
function ExtendedHurtRadius(vector HitLocation, vector AimDir, Actor HitActor)
{
local Actor Victims;
local float damageScale, dist, damageAmount;
local vector dir;
DamageAmount = RandRange(DamageMin, DamageMax) * DamageAtten;
foreach Weapon.VisibleCollidingActors(class'Actor', Victims, DamageRadius + 200, HitLocation) {
// don't let blast damage affect fluid - VisibleCollisingActors doesn't really work for them - jag
if (Victims != self && Victims.Role == ROLE_Authority && !Victims.IsA('FluidSurfaceInfo')) {
dist = DistToCylinder(Victims.Location - HitLocation, Victims.CollisionHeight, Victims.CollisionRadius);
if ( dist > DamageRadius )
continue;
dir = Normal(Victims.Location - HitLocation);
if (Victims == HitActor)
dir = Normal(dir + AimDir);
damageScale = 1 - FMax(0, dist / DamageRadius);
Victims.TakeDamage(damageScale * DamageAmount, Instigator, Victims.Location - 0.5 * (Victims.CollisionHeight + Victims.CollisionRadius) * dir, damageScale * Momentum * dir, DamageType);
if (Vehicle(Victims) != None && Vehicle(Victims).Health > 0)
Vehicle(Victims).DriverRadiusDamage(DamageAmount, DamageRadius, Instigator.Controller, DamageType, Momentum, HitLocation);
}
}
}
/**
Calculates a point's distance to a cylinder.
*/
static final function float DistToCylinder(vector CenterDist, float HalfHeight, float Radius)
{
CenterDist.X = VSize(vect(1,1,0) * CenterDist) - Radius;
if (CenterDist.X < 0)
CenterDist.X = 0;
CenterDist.Y = 0;
if (CenterDist.Z < 0)
CenterDist.Z *= -1;
CenterDist.Z -= HalfHeight;
if (CenterDist.Z < 0)
CenterDist.Z = 0;
return VSize(CenterDist);
}
This roughly works as follows: ExtendedHurtRadius picks out all actors within the desired radius as well as actors that are relatively close to the outer bounds of the "damage sphere". It then uses DistToCylinder to calculate the actual distance from the center to the outer bounds of each actor's collision cylinder.
For obvious reasons this code only works with target actors that use cylinder collision. Static mesh collision will break this code because those actors' collision cylinder size might not be related to the actual collision shape.