Download

Projectile Damage Degradation by distance

How are you supposed to handle a projectile’s damage degradation without using timelines?

I think I’m on the right track with this code, but need your guys help. FDHProjectileDamage::Tick() will be called from the owning projectile’s Tick()
So what I’m trying to do here, is this:

1163c71541c130a66276b24e68347a6ae1fa5328.png

Here’s the code:


/** FDHProjectileDamage
 * Declared: DHItemTypes.h
 *
 * Handles the damage properties of a projectile
 */
USTRUCT(BlueprintType)
struct FDHProjectileDamage
{
	GENERATED_USTRUCT_BODY();
public:
	/** Default constructor */
	FDHProjectileDamage() {}
	FDHProjectileDamage(float InDegStartRange, float InDegIntervalRange, float InDegScale, float InInitDamage, float InMinDmg, float InSpeed);

	//////////////////////////////////////////////////////////////////////////
	// Projectile damage

	/** Travel distance required to start degradation */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float DegStartRange;
	/** Travel distance interval to degrade damage by degradation scale */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float DegIntervalRange;
	/** Scale to apply every degradation cycle */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float DegScale;
	/** Initial (maximum in most cases) damage */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float InitialDamage;
	/** Minimum damage, where degradation stops */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float MinDamage;
	/** Speed of projectile (UU/s) */
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float Speed;

	/** Call every owner tick */
	FORCEINLINE void Tick(float DeltaSeconds);
	/** Gets current damage
	 * @returns					Current damage */
	FORCEINLINE float Current() const;
	operator float() const { return Current(); }

private:
	float CurrentDmg;
	float CurrentTime;
	float TravelDist;
};

FDHProjectileDamage::FDHProjectileDamage(float InDegStartRange, float InDegIntervalRange, float InDegScale, float InInitDamage, float InMinDmg, float InSpeed)
	: DegStartRange(InDegStartRange)
	, DegIntervalRange(InDegIntervalRange)
	, DegScale(InDegScale)
	, InitialDamage(InInitDamage)
	, MinDamage(InMinDmg)
	, Speed(InSpeed)
	, CurrentDmg(InitialDamage)
	, CurrentTime(0.0f)
	, TravelDist(0.0f) {}

//////////////////////////////////////////////////////////////////////////
// Projectile damage

void FDHProjectileDamage::Tick(float DeltaSeconds)
{
	float OldTravelDist = TravelDist;
	TravelDist += Speed * DeltaSeconds;
	CurrentTime += DeltaSeconds;
	
	if (TravelDist >= DegStartRange && CurrentDmg * DegScale >= MinDamage)
	{
		TravelDist - DegStartRange;
	}
}

What speaks against a timeline or some sort of curve in general?

Why not cache it’s spawn location, Subtract from the impact location and find the length, and use that to work out how much to reduce the damage?

That seems like the simplest way. Timeline/timed-based method seems over complicated.

It’s harder to display in item storefront UI

Probably right. I’ll try to implement it

You could simply subtract from the projectiles damage upon each tick (remember to scale the subtraction by delta time).

Just take time difference between spawn and impact, and work your way from there.