I think, i am not tooo far away right now, but what am i doing wrong now ???
It’s not working this way …
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "MilitaryEntity.generated.h"
// Dynamic multicast delegate to broadcast entity death
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMilitaryEntityDelegateDeath);
/// Forward Decleration definitions to keep headers clear
class UArrowComponent;
class UAimingComponent;
class UAudioEffectComponent;
class UTurret;
// Abstract implementation of an military entity inside the game
UCLASS(abstract)
class TURRETPOWER_API AMilitaryEntity : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMilitaryEntity();
// OnDeath Delegator to broadcast entities death
FMilitaryEntityDelegateDeath OnDeath;
virtual void OnConstruction(const FTransform& Transform) override;
#pragma region BlueprintImplementableEvents
// Blueprint implementable event to show individual Barrel Fire
UFUNCTION(BlueprintImplementableEvent, Category = "Setup")
void OnBarrelFire();
// Blueprint implementable event to show individual Destruction
UFUNCTION(BlueprintImplementableEvent, Category = "Setup")
void OnDestruction();
// Blueprint implementable event to make something on turret rotation
UFUNCTION(BlueprintImplementableEvent, Category = "Setup")
void OnTurretRotate(bool IsPrimaryTurret);
// Blueprint implementable event to make something on barrel lift
UFUNCTION(BlueprintImplementableEvent, Category = "Setup")
void OnBarrelMove(bool IsPrimaryTurret);
#pragma endregion to handle special behaviour on action
// Return value, if actor is locked on
UFUNCTION(BlueprintCallable, Category = "Setup")
AActor* GetLockedOnTarget() const;
// Sets an Actor as Locked on target
void SetLockedOnTarget(AActor* Target);
// Blueprint Callable implementation for inherited primary turret
UFUNCTION(BlueprintCallable, Category = "Setup")
UTurret* GetPrimaryTurret() const;
// Blueprint Callable implementation for inherited primary turret
UFUNCTION(BlueprintCallable, Category = "Setup")
UTurret* GetSecondaryTurret() const;
// Blueprint Callable implementation for inherited body
UFUNCTION(BlueprintCallable, Category = "Setup")
UStaticMeshComponent* GetBody() const;
// Blueprint Callable implementation for inherited Aiming Component
UFUNCTION(BlueprintCallable, Category = "Setup")
UAimingComponent* GetAimingComponent() const;
// Blueprint Callable implementation for inherited AudioComponent
UFUNCTION(BlueprintCallable, Category = "Setup")
UAudioEffectComponent* GetAudioComponent() const;
/// Visibility functionality
// Visibility passthroug callable
UFUNCTION(BlueprintCallable, Category = "Game")
void SetVisibility(bool Visibility);
// is Pawn is Visible to player
UFUNCTION(BlueprintImplementableEvent, Category = "Setup")
void VisibleToPlayer(bool isVisible);
protected:
// TODO put into Player Controller !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Flag indicating, First Person Camera is used
UPROPERTY(BlueprintReadWrite, Category = "Camera")
bool isUsingFirstPerson = false;
// Pointer to the Locked on target
AActor* LockedOnTarget;
#pragma region Debug
// Shows Debug Direction Arrows
UPROPERTY(EditAnywhere, Category = "Debug")
bool ShowArrows = true;
// Arrow showing into the primary barrels direction
UPROPERTY(VisibleAnywhere, Category = "Components")
UArrowComponent* PrimaryDirection = nullptr;
// Arrow showing into the secondary barrels direction
UPROPERTY(VisibleAnywhere, Category = "Components")
UArrowComponent* SecondaryDirection = nullptr;
// Outliner Folder name for editor play sorting
UPROPERTY(EditDefaultsOnly, Category = "Components")
FName EditorOutlinerFolderName = "Entities";
#pragma endregion information seen on the entity
private:
virtual void BeginPlay() override;
#pragma region Components and Meshes
// Body of this entity
UPROPERTY(VisibleAnywhere, Category = "Components")
UStaticMeshComponent* Body = nullptr;
// Primary turret of this entity
UPROPERTY(VisibleAnywhere, Category = "Components")
UTurret* PrimaryTurret = nullptr;
// Secondary Turret of this entity
UPROPERTY(VisibleAnywhere, Category = "Components")
UTurret* SecondaryTurret = nullptr;
// Aiming Component for this entity
UPROPERTY(VisibleAnywhere, Category = "Components")
UAimingComponent* AimingComponent = nullptr;
// Audio Component for this entity
UPROPERTY(VisibleAnywhere, Category = "Components")
UAudioEffectComponent* AudioComponent = nullptr;
#pragma endregion of this actors military entity without barrels or extras
#pragma region Life
protected:
// Called by the engine, when actor damage is dealt
virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCause) override;
// Health Percentage for the current actor
UFUNCTION(BlueprintPure, Category = "Health")
float GetHealthPercent() const;
// current lifes left
UFUNCTION(BlueprintCallable, Category = "Lifes")
int GetLifesLeft() const;
// Starting Health Points to act. EditAnywhere to set individual Health Points
UPROPERTY(EditAnywhere, Category = "Setup")
int32 StartingHealth = 100;
// Current Health for this actor
UPROPERTY(VisibleAnywhere, Category = "Health")
int32 CurrentHealth = 0;
// Starting Life Count
UPROPERTY(EditDefaultsOnly, Category = "Setup")
int32 StartingLifes = 0;
// Current Lifes left
UPROPERTY(VisibleAnywhere, Category = "Lifes")
int32 CurrentLifes = 0;
#pragma endregion Settings for Life and Health
};
#include "MilitaryEntity.h"
#include "Components/StaticMeshComponent.h"
#include "Components/ArrowComponent.h"
#include "AimingComponent.h"
#include "AudioEffectComponent.h"
#include "Turret.h"
#include "BarrelInterface.h"
#include "AbstractBarrel.h"
float AMilitaryEntity::TakeDamage(float DamageAmount, FDamageEvent const & DamageEvent, AController * EventInstigator, AActor * DamageCause)
{
// Round the damage amount
int32 DamagePoints = FPlatformMath::RoundToInt(DamageAmount);
// Clamp the Damage to apply between 0 and the current health ans max
auto DamageToApply = FMath::Clamp<int32>(DamagePoints, 0, CurrentHealth);
//UE_LOG(LogTemp, Warning, TEXT("DamageAmount:%f ,DamageToApply:%i"), DamageAmount, DamageToApply)
// Apply damage
CurrentHealth -= DamageToApply;
// if current health is below or equal 0
if (CurrentHealth <= 0)
{
// Count down lifes
CurrentLifes--;
// if no more lifes left
if (CurrentLifes <= 0)
{
// Call entities destruction behaviour
OnDestruction();
// Broadcast destruction of this entity
OnDeath.Broadcast();
}
else
{
CurrentHealth = StartingHealth;
// TODO respawn in a small distance of time and place
}
}
return DamageToApply;
}
// Initializes the entities instances
void AMilitaryEntity::OnConstruction(const FTransform& Transform)
{
Super::OnConstruction(Transform);
/// Attach all objects to its given location
if (Body->GetSocketByName("TurretSocket"))
PrimaryTurret->AttachToComponent(Body, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), TEXT("TurretSocket"));
else
PrimaryTurret->AttachToComponent(Body, FAttachmentTransformRules::KeepRelativeTransform);
if (PrimaryTurret->GetSocketByName("SecondarySocket"))
SecondaryTurret->AttachToComponent(PrimaryTurret, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), TEXT("SecondarySocket"));
else
SecondaryTurret->AttachToComponent(PrimaryTurret, FAttachmentTransformRules::KeepRelativeTransform);
if (PrimaryTurret)
{
if (PrimaryTurret->GetSocketByName("BarrelSocket"))
PrimaryDirection->AttachToComponent(PrimaryTurret, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), TEXT("BarrelSocket"));
else
PrimaryDirection->AttachToComponent(PrimaryTurret, FAttachmentTransformRules::KeepRelativeTransform);
/// Toggle the Arrows Debug visibility with ShowArrows value
if (ShowArrows)
PrimaryDirection->SetVisibility(true);
else
PrimaryDirection->SetVisibility(false);
}
if (SecondaryTurret)
{
if (SecondaryTurret && SecondaryTurret->GetSocketByName("BarrelSocket"))
SecondaryDirection->AttachToComponent(SecondaryTurret, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), TEXT("BarrelSocket"));
else
SecondaryDirection->AttachToComponent(SecondaryTurret, FAttachmentTransformRules::KeepRelativeTransform);
SecondaryDirection->SetWorldScale3D(FVector(.5f));
/// Toggle the Arrows Debug visibility with ShowArrows value
if (ShowArrows)
SecondaryDirection->SetVisibility(true);
else
SecondaryDirection->SetVisibility(false);
}
}
// BeginPlay innitializes Health, Life, Ammo and Fuel
// TODO Ammo and Fuel implementation
void AMilitaryEntity::BeginPlay()
{
Super::BeginPlay();
CurrentHealth = StartingHealth;
CurrentLifes = StartingLifes;
#if WITH_EDITOR
SetFolderPath(EditorOutlinerFolderName);
#endif
}
/// Getter Methods
AActor* AMilitaryEntity::GetLockedOnTarget() const { return LockedOnTarget; }
UTurret* AMilitaryEntity::GetPrimaryTurret() const { return PrimaryTurret; }
UTurret* AMilitaryEntity::GetSecondaryTurret() const { return SecondaryTurret; }
UAimingComponent* AMilitaryEntity::GetAimingComponent() const { return AimingComponent; }
UStaticMeshComponent * AMilitaryEntity::GetBody() const{return Body; }
UAudioEffectComponent * AMilitaryEntity::GetAudioComponent() const { return AudioComponent; }
int AMilitaryEntity::GetLifesLeft() const { return CurrentLifes; }
float AMilitaryEntity::GetHealthPercent() const { return float(CurrentHealth) / float(StartingHealth); }
/// Setter Methods
void AMilitaryEntity::SetVisibility(bool Visibility) { VisibleToPlayer(Visibility); }
void AMilitaryEntity::SetLockedOnTarget(AActor* Target) { LockedOnTarget = Target; }
/// Constructor
AMilitaryEntity::AMilitaryEntity()
{
PrimaryActorTick.bCanEverTick = true;
Body = CreateDefaultSubobject<UStaticMeshComponent>(FName("Body"));
PrimaryTurret = CreateDefaultSubobject<UTurret>(FName("PrimaryTurret"));
SecondaryTurret = CreateDefaultSubobject<UTurret>(FName("SecondaryTurret"));
PrimaryDirection = CreateDefaultSubobject<UArrowComponent>(FName("Primary Direction"));
SecondaryDirection = CreateDefaultSubobject<UArrowComponent>(FName("Secondary Direction"));
AudioComponent = CreateDefaultSubobject<UAudioEffectComponent>(FName("Audio Component"));
AimingComponent = CreateDefaultSubobject<UAimingComponent>(FName("Aiming Component"));
}
#pragma once
#include "CoreMinimal.h"
#include "MilitaryEntity.h"
#include "TurretEntity.generated.h"
class UBarrel;
class UStaticMeshComponent;
UCLASS()
class TURRETPOWER_API ATurretEntity : public AMilitaryEntity
{
GENERATED_BODY()
public:
ATurretEntity();
virtual void OnConstruction(const FTransform& Transform) override;
UFUNCTION(BlueprintCallable, Category = "Setup")
UBarrel* GetPrimaryBarrel();
UFUNCTION(BlueprintCallable, Category = "Setup")
UBarrel* GetSecondaryBarrel();
protected:
// Socket scale is to scale the socket and rescale down the body afterwards
UPROPERTY(EditDefaultsOnly, Category = "Setup")
FVector SocketScale = FVector(1.f,1.f,1.f);
// Socket is Showing
UPROPERTY(VisibleAnywhere, Category = "Components")
UStaticMeshComponent* Socket = nullptr;
UPROPERTY(VisibleAnywhere, Category = "Components")
UBarrel* PrimaryBarrel = nullptr;
UPROPERTY(VisibleAnywhere, Category = "Components")
UBarrel* SecondaryBarrel = nullptr;
};
#include "TurretEntity.h"
#include "Components/ArrowComponent.h"
#include "Components/StaticMeshComponent.h"
#include "AimingComponent.h"
#include "Barrel.h"
#include "Turret.h"
ATurretEntity::ATurretEntity() : AMilitaryEntity()
{
Socket = CreateDefaultSubobject<UStaticMeshComponent>(FName("BodySocket"));
PrimaryBarrel = CreateDefaultSubobject<UBarrel>(FName("PrimaryBarrel"));
SecondaryBarrel = CreateDefaultSubobject<UBarrel>(FName("SecondaryBarrel"));
RootComponent = Socket;
}
void ATurretEntity::OnConstruction(const FTransform& Transform)
{
Super::OnConstruction(Transform);
FVector Scale = FVector(1.0f);
if (Socket)
{
Socket->SetWorldScale3D(Scale * SocketScale);
}
if (GetBody())
{
if (Socket->GetSocketByName("BodySocket"))
GetBody()->AttachToComponent(Socket, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), TEXT("BodySocket"));
else
GetBody()->AttachToComponent(Socket, FAttachmentTransformRules::KeepRelativeTransform);
// GetBody()->SetWorldScale3D(Scale/SocketScale);
}
if (GetPrimaryTurret())
{
if (GetPrimaryTurret()->GetSocketByName("BarrelSocket"))
PrimaryBarrel->AttachToComponent(GetPrimaryTurret(), FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), TEXT("BarrelSocket"));
else
PrimaryBarrel->AttachToComponent(GetPrimaryTurret(), FAttachmentTransformRules::KeepRelativeTransform);
}
if (GetSecondaryTurret())
{
if (GetSecondaryTurret()->GetSocketByName("SecondaryBarrelSocket"))
SecondaryBarrel->AttachToComponent(GetSecondaryTurret(), FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), TEXT("SecondaryBarrelSocket"));
else
SecondaryBarrel->AttachToComponent(GetSecondaryTurret(), FAttachmentTransformRules::KeepRelativeTransform);
}
if (PrimaryBarrel->GetSocketByName("MuzzleSocket"))
PrimaryDirection->AttachToComponent(PrimaryBarrel, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), TEXT("MuzzleSocket"));
else
PrimaryDirection->AttachToComponent(PrimaryBarrel, FAttachmentTransformRules::KeepRelativeTransform);
if (SecondaryBarrel->GetSocketByName("MuzzleSocket"))
SecondaryDirection->AttachToComponent(SecondaryBarrel, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, true), TEXT("MuzzleSocket"));
else
SecondaryDirection->AttachToComponent(SecondaryBarrel, FAttachmentTransformRules::KeepRelativeTransform);
GetAimingComponent()->Initialize(GetPrimaryTurret(), PrimaryBarrel, GetSecondaryTurret(), SecondaryBarrel, GetAudioComponent());
}
UBarrel * ATurretEntity::GetPrimaryBarrel()
{
return PrimaryBarrel;
}
UBarrel * ATurretEntity::GetSecondaryBarrel()
{
return SecondaryBarrel;
}