252 lines
9.6 KiB
C
252 lines
9.6 KiB
C
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include "CoreMinimal.h"
|
||
|
#include "Curves/CurveFloat.h"
|
||
|
|
||
|
#include "LyraWeaponInstance.h"
|
||
|
#include "AbilitySystem/LyraAbilitySourceInterface.h"
|
||
|
|
||
|
#include "LyraRangedWeaponInstance.generated.h"
|
||
|
|
||
|
class UPhysicalMaterial;
|
||
|
|
||
|
/**
|
||
|
* ULyraRangedWeaponInstance
|
||
|
*
|
||
|
* A piece of equipment representing a ranged weapon spawned and applied to a pawn
|
||
|
*/
|
||
|
UCLASS()
|
||
|
class ULyraRangedWeaponInstance : public ULyraWeaponInstance, public ILyraAbilitySourceInterface
|
||
|
{
|
||
|
GENERATED_BODY()
|
||
|
|
||
|
public:
|
||
|
ULyraRangedWeaponInstance(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
|
||
|
|
||
|
virtual void PostLoad() override;
|
||
|
|
||
|
#if WITH_EDITOR
|
||
|
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
|
||
|
|
||
|
void UpdateDebugVisualization();
|
||
|
#endif
|
||
|
|
||
|
int32 GetBulletsPerCartridge() const
|
||
|
{
|
||
|
return BulletsPerCartridge;
|
||
|
}
|
||
|
|
||
|
/** Returns the current spread angle (in degrees, diametrical) */
|
||
|
float GetCalculatedSpreadAngle() const
|
||
|
{
|
||
|
return CurrentSpreadAngle;
|
||
|
}
|
||
|
|
||
|
float GetCalculatedSpreadAngleMultiplier() const
|
||
|
{
|
||
|
return bHasFirstShotAccuracy ? 0.0f : CurrentSpreadAngleMultiplier;
|
||
|
}
|
||
|
|
||
|
bool HasFirstShotAccuracy() const
|
||
|
{
|
||
|
return bHasFirstShotAccuracy;
|
||
|
}
|
||
|
|
||
|
float GetSpreadExponent() const
|
||
|
{
|
||
|
return SpreadExponent;
|
||
|
}
|
||
|
|
||
|
float GetMaxDamageRange() const
|
||
|
{
|
||
|
return MaxDamageRange;
|
||
|
}
|
||
|
|
||
|
float GetBulletTraceSweepRadius() const
|
||
|
{
|
||
|
return BulletTraceSweepRadius;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
#if WITH_EDITORONLY_DATA
|
||
|
UPROPERTY(VisibleAnywhere, Category = "Spread|Fire Params")
|
||
|
float Debug_MinHeat = 0.0f;
|
||
|
|
||
|
UPROPERTY(VisibleAnywhere, Category = "Spread|Fire Params")
|
||
|
float Debug_MaxHeat = 0.0f;
|
||
|
|
||
|
UPROPERTY(VisibleAnywhere, Category="Spread|Fire Params", meta=(ForceUnits=deg))
|
||
|
float Debug_MinSpreadAngle = 0.0f;
|
||
|
|
||
|
UPROPERTY(VisibleAnywhere, Category="Spread|Fire Params", meta=(ForceUnits=deg))
|
||
|
float Debug_MaxSpreadAngle = 0.0f;
|
||
|
|
||
|
UPROPERTY(VisibleAnywhere, Category="Spread Debugging")
|
||
|
float Debug_CurrentHeat = 0.0f;
|
||
|
|
||
|
UPROPERTY(VisibleAnywhere, Category="Spread Debugging", meta = (ForceUnits=deg))
|
||
|
float Debug_CurrentSpreadAngle = 0.0f;
|
||
|
|
||
|
// The current *combined* spread angle multiplier
|
||
|
UPROPERTY(VisibleAnywhere, Category = "Spread Debugging", meta=(ForceUnits=x))
|
||
|
float Debug_CurrentSpreadAngleMultiplier = 1.0f;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
// Spread exponent, affects how tightly shots will cluster around the center line
|
||
|
// when the weapon has spread (non-perfect accuracy). Higher values will cause shots
|
||
|
// to be closer to the center (default is 1.0 which means uniformly within the spread range)
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, meta=(ClampMin=0.1), Category="Spread|Fire Params")
|
||
|
float SpreadExponent = 1.0f;
|
||
|
|
||
|
// A curve that maps the heat to the spread angle
|
||
|
// The X range of this curve typically sets the min/max heat range of the weapon
|
||
|
// The Y range of this curve is used to define the min and maximum spread angle
|
||
|
UPROPERTY(EditAnywhere, Category = "Spread|Fire Params")
|
||
|
FRuntimeFloatCurve HeatToSpreadCurve;
|
||
|
|
||
|
// A curve that maps the current heat to the amount a single shot will further 'heat up'
|
||
|
// This is typically a flat curve with a single data point indicating how much heat a shot adds,
|
||
|
// but can be other shapes to do things like punish overheating by adding progressively more heat.
|
||
|
UPROPERTY(EditAnywhere, Category="Spread|Fire Params")
|
||
|
FRuntimeFloatCurve HeatToHeatPerShotCurve;
|
||
|
|
||
|
// A curve that maps the current heat to the heat cooldown rate per second
|
||
|
// This is typically a flat curve with a single data point indicating how fast the heat
|
||
|
// wears off, but can be other shapes to do things like punish overheating by slowing down
|
||
|
// recovery at high heat.
|
||
|
UPROPERTY(EditAnywhere, Category="Spread|Fire Params")
|
||
|
FRuntimeFloatCurve HeatToCoolDownPerSecondCurve;
|
||
|
|
||
|
// Time since firing before spread cooldown recovery begins (in seconds)
|
||
|
UPROPERTY(EditAnywhere, Category="Spread|Fire Params", meta=(ForceUnits=s))
|
||
|
float SpreadRecoveryCooldownDelay = 0.0f;
|
||
|
|
||
|
// Should the weapon have perfect accuracy when both player and weapon spread are at their minimum value
|
||
|
UPROPERTY(EditAnywhere, Category="Spread|Fire Params")
|
||
|
bool bAllowFirstShotAccuracy = false;
|
||
|
|
||
|
// Multiplier when in an aiming camera mode
|
||
|
UPROPERTY(EditAnywhere, Category="Spread|Player Params", meta=(ForceUnits=x))
|
||
|
float SpreadAngleMultiplier_Aiming = 1.0f;
|
||
|
|
||
|
// Multiplier when standing still or moving very slowly
|
||
|
// (starts to fade out at StandingStillSpeedThreshold, and is gone completely by StandingStillSpeedThreshold + StandingStillToMovingSpeedRange)
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Spread|Player Params", meta=(ForceUnits=x))
|
||
|
float SpreadAngleMultiplier_StandingStill = 1.0f;
|
||
|
|
||
|
// Rate at which we transition to/from the standing still accuracy (higher values are faster, though zero is instant; @see FInterpTo)
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Spread|Player Params")
|
||
|
float TransitionRate_StandingStill = 5.0f;
|
||
|
|
||
|
// Speeds at or below this are considered standing still
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Spread|Player Params", meta=(ForceUnits="cm/s"))
|
||
|
float StandingStillSpeedThreshold = 80.0f;
|
||
|
|
||
|
// Speeds no more than this above StandingStillSpeedThreshold are used to feather down the standing still bonus until it's back to 1.0
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Spread|Player Params", meta=(ForceUnits="cm/s"))
|
||
|
float StandingStillToMovingSpeedRange = 20.0f;
|
||
|
|
||
|
|
||
|
// Multiplier when crouching, smoothly blended to based on TransitionRate_Crouching
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Spread|Player Params", meta=(ForceUnits=x))
|
||
|
float SpreadAngleMultiplier_Crouching = 1.0f;
|
||
|
|
||
|
// Rate at which we transition to/from the crouching accuracy (higher values are faster, though zero is instant; @see FInterpTo)
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Spread|Player Params")
|
||
|
float TransitionRate_Crouching = 5.0f;
|
||
|
|
||
|
|
||
|
// Spread multiplier while jumping/falling, smoothly blended to based on TransitionRate_JumpingOrFalling
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Spread|Player Params", meta=(ForceUnits=x))
|
||
|
float SpreadAngleMultiplier_JumpingOrFalling = 1.0f;
|
||
|
|
||
|
// Rate at which we transition to/from the jumping/falling accuracy (higher values are faster, though zero is instant; @see FInterpTo)
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Spread|Player Params")
|
||
|
float TransitionRate_JumpingOrFalling = 5.0f;
|
||
|
|
||
|
// Number of bullets to fire in a single cartridge (typically 1, but may be more for shotguns)
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Weapon Config")
|
||
|
int32 BulletsPerCartridge = 1;
|
||
|
|
||
|
// The maximum distance at which this weapon can deal damage
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Weapon Config", meta=(ForceUnits=cm))
|
||
|
float MaxDamageRange = 25000.0f;
|
||
|
|
||
|
// The radius for bullet traces sweep spheres (0.0 will result in a line trace)
|
||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Weapon Config", meta=(ForceUnits=cm))
|
||
|
float BulletTraceSweepRadius = 0.0f;
|
||
|
|
||
|
// A curve that maps the distance (in cm) to a multiplier on the base damage from the associated gameplay effect
|
||
|
// If there is no data in this curve, then the weapon is assumed to have no falloff with distance
|
||
|
UPROPERTY(EditAnywhere, Category = "Weapon Config")
|
||
|
FRuntimeFloatCurve DistanceDamageFalloff;
|
||
|
|
||
|
// List of special tags that affect how damage is dealt
|
||
|
// These tags will be compared to tags in the physical material of the thing being hit
|
||
|
// If more than one tag is present, the multipliers will be combined multiplicatively
|
||
|
UPROPERTY(EditAnywhere, Category = "Weapon Config")
|
||
|
TMap<FGameplayTag, float> MaterialDamageMultiplier;
|
||
|
|
||
|
private:
|
||
|
// Time since this weapon was last fired (relative to world time)
|
||
|
double LastFireTime = 0.0;
|
||
|
|
||
|
// The current heat
|
||
|
float CurrentHeat = 0.0f;
|
||
|
|
||
|
// The current spread angle (in degrees, diametrical)
|
||
|
float CurrentSpreadAngle = 0.0f;
|
||
|
|
||
|
// Do we currently have first shot accuracy?
|
||
|
bool bHasFirstShotAccuracy = false;
|
||
|
|
||
|
// The current *combined* spread angle multiplier
|
||
|
float CurrentSpreadAngleMultiplier = 1.0f;
|
||
|
|
||
|
// The current standing still multiplier
|
||
|
float StandingStillMultiplier = 1.0f;
|
||
|
|
||
|
// The current jumping/falling multiplier
|
||
|
float JumpFallMultiplier = 1.0f;
|
||
|
|
||
|
// The current crouching multiplier
|
||
|
float CrouchingMultiplier = 1.0f;
|
||
|
|
||
|
public:
|
||
|
void Tick(float DeltaSeconds);
|
||
|
|
||
|
//~ULyraEquipmentInstance interface
|
||
|
virtual void OnEquipped();
|
||
|
virtual void OnUnequipped();
|
||
|
//~End of ULyraEquipmentInstance interface
|
||
|
|
||
|
void AddSpread();
|
||
|
|
||
|
//~ILyraAbilitySourceInterface interface
|
||
|
virtual float GetDistanceAttenuation(float Distance, const FGameplayTagContainer* SourceTags = nullptr, const FGameplayTagContainer* TargetTags = nullptr) const override;
|
||
|
virtual float GetPhysicalMaterialAttenuation(const UPhysicalMaterial* PhysicalMaterial, const FGameplayTagContainer* SourceTags = nullptr, const FGameplayTagContainer* TargetTags = nullptr) const override;
|
||
|
//~End of ILyraAbilitySourceInterface interface
|
||
|
|
||
|
private:
|
||
|
void ComputeSpreadRange(float& MinSpread, float& MaxSpread);
|
||
|
void ComputeHeatRange(float& MinHeat, float& MaxHeat);
|
||
|
|
||
|
inline float ClampHeat(float NewHeat)
|
||
|
{
|
||
|
float MinHeat;
|
||
|
float MaxHeat;
|
||
|
ComputeHeatRange(/*out*/ MinHeat, /*out*/ MaxHeat);
|
||
|
|
||
|
return FMath::Clamp(NewHeat, MinHeat, MaxHeat);
|
||
|
}
|
||
|
|
||
|
// Updates the spread and returns true if the spread is at minimum
|
||
|
bool UpdateSpread(float DeltaSeconds);
|
||
|
|
||
|
// Updates the multipliers and returns true if they are at minimum
|
||
|
bool UpdateMultipliers(float DeltaSeconds);
|
||
|
};
|