Since the radial damage functions don’t have any effect in my game, I have been trying to implement my own version, but I am running into a problem when a perform a sweep. More specifically, when I run a multi sweep, I do get a full array of all the objects that were within the sweep radius, but all the objects impact points return the same value of the first object in the array. This majorly complicates things, as I need the impact point of all the separate objects within the trace to calculate damage falloff and that doesn’t really work when all I get is the same location for every single object in the trace.
I have tried this both with c++ and blueprint, in both version 4.14 and 4.15, and they all have the same effect, so I am submitting this as a bug.
void UPA_BlueprintFunctionLibrary::DealRadialDamageWithFalloff(float MinDamage, float MaxDamage, float MinRadius, float MaxRadius, float FallOff, FVector DamageOrigin, TSubclassOf<UDamageType> DamageType, class AController* InstigatedBy, AActor* DamageCauser, FHitResult HitResult, bool bIgnoreSelf, bool bDebug)
{
if (MaxRadius != 0.f && DamageCauser)
{
FCollisionQueryParams initialTraceParams(TEXT(""), false, DamageCauser);
initialTraceParams.bTraceAsyncScene = true;
initialTraceParams.bTraceComplex = true;
initialTraceParams.bReturnPhysicalMaterial = false;
TArray<FHitResult> HitResults;
FCollisionObjectQueryParams ObjectParams;
ObjectParams.AddObjectTypesToQuery(ECC_Pawn);
ObjectParams.AddObjectTypesToQuery(ECC_WorldStatic);
ObjectParams.AddObjectTypesToQuery(ECC_WorldDynamic);
ObjectParams.AddObjectTypesToQuery(ECC_Visibility);
bool bHit = DamageCauser->GetWorld()->SweepMultiByObjectType(HitResults,
DamageOrigin,
FVector(DamageOrigin.X, DamageOrigin.Y, DamageOrigin.Z + 1.f),
FQuat::Identity,
ObjectParams,
FCollisionShape::MakeSphere(MaxRadius),
initialTraceParams);
if (bDebug)
{
DrawDebugSphere(DamageCauser->GetWorld(), DamageOrigin, MinRadius, 12, FColor::Red, false, 2.f);
DrawDebugSphere(DamageCauser->GetWorld(), DamageOrigin, MaxRadius, 12, FColor::Blue, false, 2.f);
}
if (bHit)
{
for (int32 HitIndex = 0; HitIndex < HitResults.Num(); HitIndex++)
{
if (bIgnoreSelf && HitResults[HitIndex].GetActor() == DamageCauser)
{
//do nothing
}
else
{
float ActorDistance = (DamageOrigin - HitResults[HitIndex].ImpactPoint).Size();
float const ValidatedMinRadius = FMath::Max(0.f, MinRadius);
float const ValidatedMaxRadius = FMath::Max(MaxRadius, ValidatedMinRadius);
float const ValidatedDistance = FMath::Max(0.f, ActorDistance);
// calculate the interpolated scale
float DamageScale;
if (ValidatedDistance >= ValidatedMaxRadius)
{
DamageScale = 0.f;
}
else if ((FallOff == 0.f) || (ValidatedDistance <= ValidatedMinRadius))
{
DamageScale = 1.f;
}
else
{
DamageScale = 1.f - ((ValidatedDistance - ValidatedMinRadius) / (ValidatedMaxRadius - ValidatedMinRadius));
DamageScale = FMath::Pow(DamageScale, FallOff);
}
float ActualDamage = FMath::Lerp(MinDamage, MaxDamage, FMath::Max(0.f, DamageScale));
DrawDebugPoint(DamageCauser->GetWorld(), HitResults[HitIndex].ImpactPoint, 20.f, FColor::Green, false, 2.f);
if (ActualDamage > 0.f)
UGameplayStatics::ApplyDamage(HitResults[HitIndex].GetActor(), ActualDamage, InstigatedBy, DamageCauser, DamageType);
}
}
}
}
}