RealtimeStyleTransferRuntime/Source/LyraGame/Weapons/LyraRangedWeaponInstance.h

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);
};