I am on the newer side for C++ in UE, so this may be a simple beginner misunderstanding.
I have a custom GameFeature Plugin, TUGG.
I want to add extend a base game Lyra class, ULyraGameplayAbility_FromEquipment
to add my own version of
ULyraGameplayAbility_RangedWeapon
with my own implementation.
To start, I have just copy/replaced all names from “Lyra” to “TUGG”. Everything has been renamed correctly for it to build.
I have added “LyraGame” to PrivateDependencyModuleNames, and it appears the compiler can find the files correctly, but for some reason on build, I am getting many unresolved external symbol errors that appear to reference the parent classes of ULyraGameplayAbility_FromEquipment.
This copy/paste works successfully from the game source folder, adjacent to the default Lyra one.
So what is happening? Why can I not reference base game classes from my custom GameFeature Module? Can GameFeatures not reference the base game? What is the correct way for me to extend base game Lyra classes?
UPDATE 1: Potentially relevant warning when creating the class:
Not sure what this means yet. Will update if I find out.
Here are the base classes in question:
ULyraGameplayAbility_FromEquipment .h
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystem/Abilities/LyraGameplayAbility.h"
#include "LyraGameplayAbility_FromEquipment.generated.h"
class ULyraEquipmentInstance;
class ULyraInventoryItemInstance;
/**
* ULyraGameplayAbility_FromEquipment
*
* An ability granted by and associated with an equipment instance
*/
UCLASS()
class ULyraGameplayAbility_FromEquipment : public ULyraGameplayAbility
{
GENERATED_BODY()
public:
ULyraGameplayAbility_FromEquipment(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
UFUNCTION(BlueprintCallable, Category="Lyra|Ability")
ULyraEquipmentInstance* GetAssociatedEquipment() const;
UFUNCTION(BlueprintCallable, Category = "Lyra|Ability")
ULyraInventoryItemInstance* GetAssociatedItem() const;
#if WITH_EDITOR
virtual EDataValidationResult IsDataValid(TArray<FText>& ValidationErrors) override;
#endif
};
ULyraGameplayAbility_RangedWeapon.h
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Equipment/LyraGameplayAbility_FromEquipment.h"
#include "LyraGameplayAbility_RangedWeapon.generated.h"
class ULyraRangedWeaponInstance;
class APawn;
/** Defines where an ability starts its trace from and where it should face */
UENUM(BlueprintType)
enum class ELyraAbilityTargetingSource : uint8
{
// From the player's camera towards camera focus
CameraTowardsFocus,
// From the pawn's center, in the pawn's orientation
PawnForward,
// From the pawn's center, oriented towards camera focus
PawnTowardsFocus,
// From the weapon's muzzle or location, in the pawn's orientation
WeaponForward,
// From the weapon's muzzle or location, towards camera focus
WeaponTowardsFocus,
// Custom blueprint-specified source location
Custom
};
/**
* ULyraGameplayAbility_RangedWeapon
*
* An ability granted by and associated with a ranged weapon instance
*/
UCLASS()
class ULyraGameplayAbility_RangedWeapon : public ULyraGameplayAbility_FromEquipment
{
GENERATED_BODY()
public:
ULyraGameplayAbility_RangedWeapon(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
UFUNCTION(BlueprintCallable, Category="Lyra|Ability")
ULyraRangedWeaponInstance* GetWeaponInstance() const;
//~UGameplayAbility interface
virtual bool CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags = nullptr, const FGameplayTagContainer* TargetTags = nullptr, OUT FGameplayTagContainer* OptionalRelevantTags = nullptr) const override;
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;
virtual void EndAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, bool bReplicateEndAbility, bool bWasCancelled) override;
//~End of UGameplayAbility interface
protected:
struct FRangedWeaponFiringInput
{
// Start of the trace
FVector StartTrace;
// End of the trace if aim were perfect
FVector EndAim;
// The direction of the trace if aim were perfect
FVector AimDir;
// The weapon instance / source of weapon data
ULyraRangedWeaponInstance* WeaponData = nullptr;
// Can we play bullet FX for hits during this trace
bool bCanPlayBulletFX = false;
FRangedWeaponFiringInput()
: StartTrace(ForceInitToZero)
, EndAim(ForceInitToZero)
, AimDir(ForceInitToZero)
{
}
};
protected:
static int32 FindFirstPawnHitResult(const TArray<FHitResult>& HitResults);
// Does a single weapon trace, either sweeping or ray depending on if SweepRadius is above zero
FHitResult WeaponTrace(const FVector& StartTrace, const FVector& EndTrace, float SweepRadius, bool bIsSimulated, OUT TArray<FHitResult>& OutHitResults) const;
// Wrapper around WeaponTrace to handle trying to do a ray trace before falling back to a sweep trace if there were no hits and SweepRadius is above zero
FHitResult DoSingleBulletTrace(const FVector& StartTrace, const FVector& EndTrace, float SweepRadius, bool bIsSimulated, OUT TArray<FHitResult>& OutHits) const;
// Traces all of the bullets in a single cartridge
void TraceBulletsInCartridge(const FRangedWeaponFiringInput& InputData, OUT TArray<FHitResult>& OutHits);
virtual void AddAdditionalTraceIgnoreActors(FCollisionQueryParams& TraceParams) const;
// Determine the trace channel to use for the weapon trace(s)
virtual ECollisionChannel DetermineTraceChannel(FCollisionQueryParams& TraceParams, bool bIsSimulated) const;
void PerformLocalTargeting(OUT TArray<FHitResult>& OutHits);
FVector GetWeaponTargetingSourceLocation() const;
FTransform GetTargetingTransform(APawn* SourcePawn, ELyraAbilityTargetingSource Source) const;
void OnTargetDataReadyCallback(const FGameplayAbilityTargetDataHandle& InData, FGameplayTag ApplicationTag);
UFUNCTION(BlueprintCallable)
void StartRangedWeaponTargeting();
// Called when target data is ready
UFUNCTION(BlueprintImplementableEvent)
void OnRangedWeaponTargetDataReady(const FGameplayAbilityTargetDataHandle& TargetData);
private:
FDelegateHandle OnTargetDataReadyCallbackDelegateHandle;
};