I am not taking damage!

so just recently I had like 10 errors, and it took a while to fix them, but now the tank just wont take damage, what have I done wrong? (note: the extra UE_LOGS are for debugging purposes and none of them seem to be going off)

Projectile.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

#include "GameFramework/Actor.h"

#include "Projectile.generated.h"

UCLASS()

class TOONTANKS_API AProjectile : public AActor

{

    GENERATED_BODY()

   

public:

    // Sets default values for this actor's properties

    AProjectile();

protected:

    // Called when the game starts or when spawned

    virtual void BeginPlay() override;

private:

    UPROPERTY(EditDefaultsOnly, Category = "Combat")

    UStaticMeshComponent* ProjectileMesh;

    UPROPERTY(VisibleAnywhere, Category = "Combat")

    class UProjectileMovementComponent* ProjectileMovementComponent;

    UFUNCTION()

    void OnHit(UPrimitiveComponent*

                HitComp, AActor* OtherActor,

                UPrimitiveComponent* OtherComp,

                FVector NormalImpulse,

                const FHitResult& Hit);

    UPROPERTY(EditAnywhere, Category = "Combat")

    float Damage = 50.f;

public:

    // Called every frame

    virtual void Tick(float DeltaTime) override;

   

};

Projectile.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include "Projectile.h"

#include "GameFramework/ProjectileMovementComponent.h"

#include "GameFramework/DamageType.h"

#include "Kismet/GameplayStatics.h"

// Sets default values

AProjectile::AProjectile()

{

    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.

    PrimaryActorTick.bCanEverTick = true;

    ProjectileMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Projectile Mesh"));

    RootComponent = ProjectileMesh;

    ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("Projectile Movement Component"));

    ProjectileMovementComponent->MaxSpeed = 1300.f;

    ProjectileMovementComponent->InitialSpeed = 1300.f;

}

// Called when the game starts or when spawned

void AProjectile::BeginPlay()

{

    Super::BeginPlay();

    ProjectileMesh->OnComponentHit.AddDynamic(this, &AProjectile::OnHit);

   

}

// Called every frame

void AProjectile::Tick(float DeltaTime)

{

    Super::Tick(DeltaTime);

}

void AProjectile::OnHit(UPrimitiveComponent *HitComp,

                AActor *OtherActor,

                UPrimitiveComponent *OtherComp,

                FVector NormalImpulse,

                const FHitResult& Hit)

{

    auto MyOwner = GetOwner();

    if (MyOwner == nullptr) return;

   

    auto MyOwnerInstigator = MyOwner->GetInstigatorController();

    auto DamageTypeClass = UDamageType::StaticClass();

    UE_LOG(LogTemp, Warning, TEXT("Hit"));

    if (OtherActor && OtherActor != this && OtherActor != MyOwner)

    {

        UGameplayStatics::ApplyDamage(OtherActor, Damage, MyOwnerInstigator, this, DamageTypeClass);

    }

}

HealthCompnent.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

#include "Components/ActorComponent.h"

#include "HealthComponent.generated.h"

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )

class TOONTANKS_API UHealthComponent : public UActorComponent

{

    GENERATED_BODY()

public:

    // Sets default values for this component's properties

    UHealthComponent();

protected:

    // Called when the game starts

    virtual void BeginPlay() override;

private:

    UPROPERTY(EditAnywhere)

    float MaxHealth = 100.f;

    float Health = 0.f;

    UFUNCTION()

    void DamageTaken(AActor* DamagedActor,

        float Damage,

        const UDamageType* DamageType,

        class AController* Instigator,

        AActor* DamageCauser);

public:

    // Called every frame

    virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

       

};

HealthCompnent.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include "HealthComponent.h"

// Sets default values for this component's properties

UHealthComponent::UHealthComponent()

{

    // Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features

    // off to improve performance if you don't need them.

    PrimaryComponentTick.bCanEverTick = true;

    // ...

}

// Called when the game starts

void UHealthComponent::BeginPlay()

{

    Super::BeginPlay();

    Health = MaxHealth;

    GetOwner()->OnTakeAnyDamage.AddDynamic(this, &UHealthComponent::DamageTaken);

}

// Called every frame

void UHealthComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)

{

    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

    // ...

}

void UHealthComponent::DamageTaken(AActor* DamagedActor,

        float Damage,

        const UDamageType* DamageType,

        class AController* Instigator,

        AActor* DamageCauser)

{

    UE_LOG(LogTemp, Warning, TEXT("You Have Been Hit"));

    if (Damage <= 0.f) return;

    Health -= Damage;

    UE_LOG(LogTemp, Warning, TEXT("Health: %f"), Health);

}

Are you setting the owner when you spawn the projectile?

In AProjectile::OnHit you only log if GetOwner() doesn’t return a null pointer.

I did:
Basepawn.cpp:
// Fill out your copyright notice in the Description page of Project Settings.

#include “BasePawn.h”

#include “Components/CapsuleComponent.h”

#include “Kismet/GameplayStatics.h”

#include “Projectile.h”

// Sets default values

ABasePawn::ABasePawn()

{

// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.

PrimaryActorTick.bCanEverTick = true;



CapsuleComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Capsule Collider"));

RootComponent = CapsuleComp;

BaseMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Base Mesh"));

BaseMesh->SetupAttachment(CapsuleComp);

TurretMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Turret Mesh"));

TurretMesh->SetupAttachment(BaseMesh);

ProjectileSpawnPoint = CreateDefaultSubobject<USceneComponent>(TEXT("Spawn Point"));

ProjectileSpawnPoint->SetupAttachment(TurretMesh);

}

// Called when the game starts or when spawned

void ABasePawn::RotateTurret(FVector LookAtTarget)

{

FVector ToTarget = LookAtTarget - TurretMesh->GetComponentLocation();

FRotator LookAtRotation = FRotator(0.f, ToTarget.Rotation().Yaw, 0.f);

TurretMesh->SetWorldRotation(FMath::RInterpTo(TurretMesh->GetComponentRotation(),

LookAtRotation, UGameplayStatics::GetWorldDeltaSeconds(this), 2.f));

}

void ABasePawn::Fire()

{

FVector Location = ProjectileSpawnPoint->GetComponentLocation();

FRotator Rotation = ProjectileSpawnPoint->GetComponentRotation();

auto Projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileClass, Location, Rotation);

Projectile->SetOwner(this);

}

Basepawn.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”

#include “GameFramework/Pawn.h”

#include “BasePawn.generated.h”

UCLASS()

class TOONTANKS_API ABasePawn : public APawn

{

GENERATED_BODY()

public:

// Sets default values for this pawn's properties

ABasePawn();

protected:

void RotateTurret(FVector LookAtTarget);

void Fire();

private:

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

class UCapsuleComponent* CapsuleComp;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

UStaticMeshComponent* BaseMesh;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

UStaticMeshComponent* TurretMesh;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

USceneComponent* ProjectileSpawnPoint;

UPROPERTY(EditDefaultsOnly, Category = "Combat")

TSubclassOf<class AProjectile> ProjectileClass;

};

and when I moved the log it still didn’t log it

so, after changing my function so that its more like the actual one (I must have changed a * symbol when I did not need to) I now have an error, it says that C:\Users\User\Documents\Unreal Projects\ToonTanks\Source\ToonTanks\HealthComponent.cpp(3): error C2001: newline in constant, but line 3 looks like this: #include "GameFramework/Actor.h

somehow I did not end the quotes in that line, so I fixed it

but it still does not fix the original problem, this is all the code in my current project:

BasePawn.h:
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”

#include “GameFramework/Pawn.h”

#include “BasePawn.generated.h”

UCLASS()

class TOONTANKS_API ABasePawn : public APawn

{

GENERATED_BODY()

public:

// Sets default values for this pawn's properties

ABasePawn();

protected:

void RotateTurret(FVector LookAtTarget);

void Fire();

private:

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

class UCapsuleComponent* CapsuleComp;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

UStaticMeshComponent* BaseMesh;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

UStaticMeshComponent* TurretMesh;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

USceneComponent* ProjectileSpawnPoint;

UPROPERTY(EditDefaultsOnly, Category = "Combat")

TSubclassOf<class AProjectile> ProjectileClass;

};

BasePawn.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include “BasePawn.h”

#include “Components/CapsuleComponent.h”

#include “Kismet/GameplayStatics.h”

#include “Projectile.h”

// Sets default values

ABasePawn::ABasePawn()

{

// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.

PrimaryActorTick.bCanEverTick = true;



CapsuleComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Capsule Collider"));

RootComponent = CapsuleComp;

BaseMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Base Mesh"));

BaseMesh->SetupAttachment(CapsuleComp);

TurretMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Turret Mesh"));

TurretMesh->SetupAttachment(BaseMesh);

ProjectileSpawnPoint = CreateDefaultSubobject<USceneComponent>(TEXT("Spawn Point"));

ProjectileSpawnPoint->SetupAttachment(TurretMesh);

}

// Called when the game starts or when spawned

void ABasePawn::RotateTurret(FVector LookAtTarget)

{

FVector ToTarget = LookAtTarget - TurretMesh->GetComponentLocation();

FRotator LookAtRotation = FRotator(0.f, ToTarget.Rotation().Yaw, 0.f);

TurretMesh->SetWorldRotation(FMath::RInterpTo(TurretMesh->GetComponentRotation(),

LookAtRotation, UGameplayStatics::GetWorldDeltaSeconds(this), 2.f));

}

void ABasePawn::Fire()

{

FVector Location = ProjectileSpawnPoint->GetComponentLocation();

FRotator Rotation = ProjectileSpawnPoint->GetComponentRotation();

auto Projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileClass, Location, Rotation);

Projectile->SetOwner(this);

}

Tank.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”

#include “BasePawn.h”

#include “Tank.generated.h”

/**

*/

UCLASS()

class TOONTANKS_API ATank : public ABasePawn

{

GENERATED_BODY()

public:

ATank();



// Called to bind functionality to input

virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;



// Called every frame

virtual void Tick(float DeltaTime) override;

protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;

private:

UPROPERTY(VisibleAnywhere, Category = "Components")

class USpringArmComponent* SpringArm;

UPROPERTY(VisibleAnywhere, Category = "Components")

class UCameraComponent* Camera;

UPROPERTY(EditAnywhere, Category = "Movement")

float Speed = 200.f;

UPROPERTY(EditAnywhere, Category = "Movement")

float TurnRate = 45.f;

void Move(float Value);

void Turn(float Value);

APlayerController* PlayerControllerRef;

};

Tank.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include “Tank.h”

#include “GameFramework/SpringArmComponent.h”

#include “Camera/CameraComponent.h”

#include “Components/InputComponent.h”

#include “Kismet/GameplayStatics.h”

ATank::ATank()

{

SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("Spring Arm"));

SpringArm->SetupAttachment(RootComponent);

Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));

Camera->SetupAttachment(SpringArm);

}

// Called to bind functionality to input

void ATank::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)

{

Super::SetupPlayerInputComponent(PlayerInputComponent);

PlayerInputComponent->BindAxis(TEXT("MoveForward"), this, &ATank::Move);

PlayerInputComponent->BindAxis(TEXT("Turn"), this, &ATank::Turn);

PlayerInputComponent->BindAction(TEXT("Fire"), IE_Pressed, this, &ATank::Fire);

}

// Called every frame

void ATank::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);

FHitResult HitResult;

if (PlayerControllerRef)

{

    PlayerControllerRef->GetHitResultUnderCursor(ECollisionChannel::ECC_Visibility, false, HitResult);

    //DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 25.f, 12, FColor::Red, false, -1.f);

    RotateTurret(HitResult.ImpactPoint);

}

}

void ATank::BeginPlay()

{

Super::BeginPlay();

PlayerControllerRef = Cast<APlayerController>(GetController());

}

void ATank::Move(float Value)

{

FVector DeltaLocation = FVector::ZeroVector;

DeltaLocation.X = Value * Speed * UGameplayStatics::GetWorldDeltaSeconds(this);

AddActorLocalOffset(DeltaLocation, true);

}

void ATank::Turn(float Value)

{

FRotator DeltaRotation = FRotator::ZeroRotator;

DeltaRotation.Yaw = Value * TurnRate * UGameplayStatics::GetWorldDeltaSeconds(this);

AddActorLocalRotation(DeltaRotation, true);

}

Tower.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”

#include “BasePawn.h”

#include “Tower.generated.h”

/**

*/

UCLASS()

class TOONTANKS_API ATower : public ABasePawn

{

GENERATED_BODY()

public:

virtual void Tick(float DeltaTime) override;

protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;

private:

class ATank* Tank;

UPROPERTY(EditDefaultsOnly, Category = "Combat")

float FireRange = 300.f;

FTimerHandle FireRateTimerHandle;

float FireRate = 2.f;

void CheckFireCondition();

bool InFireRange();

};

Tower.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include “Tower.h”

#include “Tank.h”

#include “Kismet/GameplayStatics.h”

#include “TimerManager.h”

// Called every frame

void ATower::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);

if(InFireRange())

{

    RotateTurret(Tank->GetActorLocation());

}

}

void ATower::BeginPlay()

{

Super::BeginPlay();



Tank = Cast<ATank>(UGameplayStatics::GetPlayerPawn(this, 0));

GetWorldTimerManager().SetTimer(FireRateTimerHandle, this, &ATower::CheckFireCondition, FireRate, true);

}

void ATower::CheckFireCondition()

{

if(InFireRange())

{



    Fire();

   

}

}

bool ATower::InFireRange()

{

if(Tank)

{

    float Distance = FVector::Dist(GetActorLocation(), Tank->GetActorLocation());

    if(Distance <= FireRange)

    {

        return true;

    }

}

return false;

}

Projectile.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include “Projectile.h”

#include “GameFramework/ProjectileMovementComponent.h”

#include “GameFramework/DamageType.h”

#include “Kismet/GameplayStatics.h”

// Sets default values

AProjectile::AProjectile()

{

// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.

PrimaryActorTick.bCanEverTick = true;

ProjectileMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Projectile Mesh"));

RootComponent = ProjectileMesh;

ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("Projectile Movement Component"));

ProjectileMovementComponent->MaxSpeed = 1300.f;

ProjectileMovementComponent->InitialSpeed = 1300.f;

}

// Called when the game starts or when spawned

void AProjectile::BeginPlay()

{

Super::BeginPlay();

ProjectileMesh->OnComponentHit.AddDynamic(this, &AProjectile::OnHit);

}

// Called every frame

void AProjectile::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);

}

void AProjectile::OnHit(UPrimitiveComponent *HitComp,

            AActor *OtherActor,

            UPrimitiveComponent *OtherComp,

            FVector NormalImpulse,

            const FHitResult& Hit)

{

auto MyOwner = GetOwner();

UE_LOG(LogTemp, Warning, TEXT("Hit"));

if (MyOwner == nullptr) return;



auto MyOwnerInstigator = MyOwner->GetInstigatorController();

auto DamageTypeClass = UDamageType::StaticClass();



if (OtherActor && OtherActor != this && OtherActor != MyOwner)

{

    UGameplayStatics::ApplyDamage(OtherActor, Damage, MyOwnerInstigator, this, DamageTypeClass);

}

}

Projectile.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”

#include “GameFramework/Actor.h”

#include “Projectile.generated.h”

UCLASS()

class TOONTANKS_API AProjectile : public AActor

{

GENERATED_BODY()

public:

// Sets default values for this actor's properties

AProjectile();

protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;

private:

UPROPERTY(EditDefaultsOnly, Category = "Combat")

UStaticMeshComponent* ProjectileMesh;

UPROPERTY(VisibleAnywhere, Category = "Combat")

class UProjectileMovementComponent* ProjectileMovementComponent;

UFUNCTION()

void OnHit(UPrimitiveComponent*

            HitComp, AActor* OtherActor,

            UPrimitiveComponent* OtherComp,

            FVector NormalImpulse,

            const FHitResult& Hit);

UPROPERTY(EditAnywhere, Category = "Combat")

float Damage = 50.f;

public:

// Called every frame

virtual void Tick(float DeltaTime) override;

};

HealthComponent:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”

#include “GameFramework/Actor.h”

#include “Projectile.generated.h”

UCLASS()

class TOONTANKS_API AProjectile : public AActor

{

GENERATED_BODY()

public:

// Sets default values for this actor's properties

AProjectile();

protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;

private:

UPROPERTY(EditDefaultsOnly, Category = "Combat")

UStaticMeshComponent* ProjectileMesh;

UPROPERTY(VisibleAnywhere, Category = "Combat")

class UProjectileMovementComponent* ProjectileMovementComponent;

UFUNCTION()

void OnHit(UPrimitiveComponent*

            HitComp, AActor* OtherActor,

            UPrimitiveComponent* OtherComp,

            FVector NormalImpulse,

            const FHitResult& Hit);

UPROPERTY(EditAnywhere, Category = "Combat")

float Damage = 50.f;

public:

// Called every frame

virtual void Tick(float DeltaTime) override;

};

HealthComponent.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include “GameFramework/Actor.h”

#include “HealthComponent.h”

// Sets default values for this component’s properties

UHealthComponent::UHealthComponent()

{

// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features

// off to improve performance if you don't need them.

PrimaryComponentTick.bCanEverTick = true;

// ...

}

// Called when the game starts

void UHealthComponent::BeginPlay()

{

Super::BeginPlay();

Health = MaxHealth;

GetOwner()->OnTakeAnyDamage.AddDynamic(this, &UHealthComponent::DamageTaken);

}

// Called every frame

void UHealthComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)

{

Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

// ...

}

void UHealthComponent::DamageTaken(AActor *DamagedActor, float Damage, const UDamageType *DamageType, class AController *Instigator,

AActor *DamageCauser)

{

UE_LOG(LogTemp, Warning, TEXT("You Have Been Hit"));

if (Damage <= 0.f) return;

Health -= Damage;

UE_LOG(LogTemp, Warning, TEXT("Health: %f"), Health);

}

Please have the code in code blocks, this is impossible to read.

sorry,

BasePawn.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”

#include “GameFramework/Pawn.h”

#include “BasePawn.generated.h”

UCLASS()

class TOONTANKS_API ABasePawn : public APawn

{

GENERATED_BODY()

public:

// Sets default values for this pawn's properties

ABasePawn();

protected:

void RotateTurret(FVector LookAtTarget);

void Fire();

private:

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

class UCapsuleComponent* CapsuleComp;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

UStaticMeshComponent* BaseMesh;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

UStaticMeshComponent* TurretMesh;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))

USceneComponent* ProjectileSpawnPoint;

UPROPERTY(EditDefaultsOnly, Category = "Combat")

TSubclassOf<class AProjectile> ProjectileClass;

};

BasePawn.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include “BasePawn.h”

#include “Components/CapsuleComponent.h”

#include “Kismet/GameplayStatics.h”

#include “Projectile.h”

// Sets default values

ABasePawn::ABasePawn()

{

// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.

PrimaryActorTick.bCanEverTick = true;



CapsuleComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Capsule Collider"));

RootComponent = CapsuleComp;

BaseMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Base Mesh"));

BaseMesh->SetupAttachment(CapsuleComp);

TurretMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Turret Mesh"));

TurretMesh->SetupAttachment(BaseMesh);

ProjectileSpawnPoint = CreateDefaultSubobject<USceneComponent>(TEXT("Spawn Point"));

ProjectileSpawnPoint->SetupAttachment(TurretMesh);

}

// Called when the game starts or when spawned

void ABasePawn::RotateTurret(FVector LookAtTarget)

{

FVector ToTarget = LookAtTarget - TurretMesh->GetComponentLocation();

FRotator LookAtRotation = FRotator(0.f, ToTarget.Rotation().Yaw, 0.f);

TurretMesh->SetWorldRotation(FMath::RInterpTo(TurretMesh->GetComponentRotation(),

LookAtRotation, UGameplayStatics::GetWorldDeltaSeconds(this), 2.f));

}

void ABasePawn::Fire()

{

FVector Location = ProjectileSpawnPoint->GetComponentLocation();

FRotator Rotation = ProjectileSpawnPoint->GetComponentRotation();

auto Projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileClass, Location, Rotation);

Projectile->SetOwner(this);

}

Tank.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”

#include “BasePawn.h”

#include “Tank.generated.h”

/**

*/

UCLASS()

class TOONTANKS_API ATank : public ABasePawn

{

GENERATED_BODY()

public:

ATank();



// Called to bind functionality to input

virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;



// Called every frame

virtual void Tick(float DeltaTime) override;

protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;

private:

UPROPERTY(VisibleAnywhere, Category = "Components")

class USpringArmComponent* SpringArm;

UPROPERTY(VisibleAnywhere, Category = "Components")

class UCameraComponent* Camera;

UPROPERTY(EditAnywhere, Category = "Movement")

float Speed = 200.f;

UPROPERTY(EditAnywhere, Category = "Movement")

float TurnRate = 45.f;

void Move(float Value);

void Turn(float Value);

APlayerController* PlayerControllerRef;

};

Tank.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include “Tank.h”

#include “GameFramework/SpringArmComponent.h”

#include “Camera/CameraComponent.h”

#include “Components/InputComponent.h”

#include “Kismet/GameplayStatics.h”

ATank::ATank()

{

SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("Spring Arm"));

SpringArm->SetupAttachment(RootComponent);

Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));

Camera->SetupAttachment(SpringArm);

}

// Called to bind functionality to input

void ATank::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)

{

Super::SetupPlayerInputComponent(PlayerInputComponent);

PlayerInputComponent->BindAxis(TEXT("MoveForward"), this, &ATank::Move);

PlayerInputComponent->BindAxis(TEXT("Turn"), this, &ATank::Turn);

PlayerInputComponent->BindAction(TEXT("Fire"), IE_Pressed, this, &ATank::Fire);

}

// Called every frame

void ATank::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);

FHitResult HitResult;

if (PlayerControllerRef)

{

    PlayerControllerRef->GetHitResultUnderCursor(ECollisionChannel::ECC_Visibility, false, HitResult);

    //DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 25.f, 12, FColor::Red, false, -1.f);

    RotateTurret(HitResult.ImpactPoint);

}

}

void ATank::BeginPlay()

{

Super::BeginPlay();

PlayerControllerRef = Cast<APlayerController>(GetController());

}

void ATank::Move(float Value)

{

FVector DeltaLocation = FVector::ZeroVector;

DeltaLocation.X = Value * Speed * UGameplayStatics::GetWorldDeltaSeconds(this);

AddActorLocalOffset(DeltaLocation, true);

}

void ATank::Turn(float Value)

{

FRotator DeltaRotation = FRotator::ZeroRotator;

DeltaRotation.Yaw = Value * TurnRate * UGameplayStatics::GetWorldDeltaSeconds(this);

AddActorLocalRotation(DeltaRotation, true);

}

Tower.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”

#include “BasePawn.h”

#include “Tower.generated.h”

/**

*/

UCLASS()

class TOONTANKS_API ATower : public ABasePawn

{

GENERATED_BODY()

public:

virtual void Tick(float DeltaTime) override;

protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;

private:

class ATank* Tank;

UPROPERTY(EditDefaultsOnly, Category = "Combat")

float FireRange = 300.f;

FTimerHandle FireRateTimerHandle;

float FireRate = 2.f;

void CheckFireCondition();

bool InFireRange();

};

Tower.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include “Tower.h”

#include “Tank.h”

#include “Kismet/GameplayStatics.h”

#include “TimerManager.h”

// Called every frame

void ATower::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);

if(InFireRange())

{

    RotateTurret(Tank->GetActorLocation());

}

}

void ATower::BeginPlay()

{

Super::BeginPlay();



Tank = Cast<ATank>(UGameplayStatics::GetPlayerPawn(this, 0));

GetWorldTimerManager().SetTimer(FireRateTimerHandle, this, &ATower::CheckFireCondition, FireRate, true);

}

void ATower::CheckFireCondition()

{

if(InFireRange())

{



    Fire();

   

}

}

bool ATower::InFireRange()

{

if(Tank)

{

    float Distance = FVector::Dist(GetActorLocation(), Tank->GetActorLocation());

    if(Distance <= FireRange)

    {

        return true;

    }

}

return false;

}

Projectile.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include “Projectile.h”

#include “GameFramework/ProjectileMovementComponent.h”

#include “GameFramework/DamageType.h”

#include “Kismet/GameplayStatics.h”

// Sets default values

AProjectile::AProjectile()

{

// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.

PrimaryActorTick.bCanEverTick = true;

ProjectileMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Projectile Mesh"));

RootComponent = ProjectileMesh;

ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("Projectile Movement Component"));

ProjectileMovementComponent->MaxSpeed = 1300.f;

ProjectileMovementComponent->InitialSpeed = 1300.f;

}

// Called when the game starts or when spawned

void AProjectile::BeginPlay()

{

Super::BeginPlay();

ProjectileMesh->OnComponentHit.AddDynamic(this, &AProjectile::OnHit);

}

// Called every frame

void AProjectile::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);

}

void AProjectile::OnHit(UPrimitiveComponent *HitComp,

            AActor *OtherActor,

            UPrimitiveComponent *OtherComp,

            FVector NormalImpulse,

            const FHitResult& Hit)

{

UE_LOG(LogTemp, Warning, TEXT("Hit"));

auto MyOwner = GetOwner();

if (MyOwner == nullptr) return;

auto MyOwnerInstigator = MyOwner->GetInstigatorController();

auto DamageTypeClass = UDamageType::StaticClass();

if (OtherActor && OtherActor != this && OtherActor != MyOwner)

{

    UGameplayStatics::ApplyDamage(OtherActor, Damage, MyOwnerInstigator, this, DamageTypeClass);

    Destroy();

}

}

Projectile.h:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include “CoreMinimal.h”

#include “GameFramework/Actor.h”

#include “Projectile.generated.h”

UCLASS()

class TOONTANKS_API AProjectile : public AActor

{

GENERATED_BODY()

public:

// Sets default values for this actor's properties

AProjectile();

protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;

private:

UPROPERTY(EditDefaultsOnly, Category = "Combat")

UStaticMeshComponent* ProjectileMesh;

UPROPERTY(VisibleAnywhere, Category = "Combat")

class UProjectileMovementComponent* ProjectileMovementComponent;

UFUNCTION()

void OnHit(UPrimitiveComponent*

            HitComp, AActor* OtherActor,

            UPrimitiveComponent* OtherComp,

            FVector NormalImpulse,

            const FHitResult& Hit);

UPROPERTY(EditAnywhere, Category = "Combat")

float Damage = 50.f;

public:

// Called every frame

virtual void Tick(float DeltaTime) override;

};

HealthComponent.h:

// Fill out your copyright notice in the Description page of Project Settings.

#include “Components/ActorComponent.h”

#include “HealthComponent.generated.h”

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )

class TOONTANKS_API UHealthComponent : public UActorComponent

{

GENERATED_BODY()

public:

// Sets default values for this component's properties

UHealthComponent();

protected:

// Called when the game starts

virtual void BeginPlay() override;

private:

UPROPERTY(EditAnywhere)

float MaxHealth = 100.f;

float Health = 0.f;

UFUNCTION()

void DamageTaken(AActor *DamagedActor, float Damage, const UDamageType *DamageType, class AController *Instigator,

AActor *DamageCauser);

public:

// Called every frame

virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

};

HealthComponent.cpp:

// Fill out your copyright notice in the Description page of Project Settings.

#include “GameFramework/Actor.h”

#include “HealthComponent.h”

// Sets default values for this component’s properties

UHealthComponent::UHealthComponent()

{

// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features

// off to improve performance if you don't need them.

PrimaryComponentTick.bCanEverTick = true;

// ...

}

// Called when the game starts

void UHealthComponent::BeginPlay()

{

Super::BeginPlay();

Health = MaxHealth;

GetOwner()->OnTakeAnyDamage.AddDynamic(this, &UHealthComponent::DamageTaken);

}

// Called every frame

void UHealthComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)

{

Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

// ...

}

void UHealthComponent::DamageTaken(AActor *DamagedActor, float Damage, const UDamageType *DamageType, class AController *Instigator,

AActor *DamageCauser)

{

UE_LOG(LogTemp, Warning, TEXT("You Have Been Hit"));

if (Damage <= 0.f) return;

Health -= Damage;

UE_LOG(LogTemp, Warning, TEXT("Health: %f"), Health);

}

Would you mind sending me your project using the following link?
https://gdev.tv/projectupload
Please use File > Zip Project within Unreal as this will ensure only required files are zipped up and things like the Binaries are excluded.

once I send it to you, you need to open up the main map, because the cpp doesn’t work if I load anything that has cpp in it before compiling for some reason, so don’t be surprised if you land in a bank map

Seems to be working fine on my end.

Have you seen the lecture titled “Live Coding Issues”? Are you building with Unreal closed before you re-open the project?

It just pretty much destroys the tank and turret if I don’t compile in unreal

but I don’t really need this problem solved, I only told you that in case you thought the file was corrupted or something, the real problem is as I have said, none of the UE_LOG’s that say that the projectile has hit something damaged the tank is going off

It’s very likely you’re using the wrong build task when compiling with VS Code. There are editor and non-editor versions of each configuration. You’re using the Unreal Editor so you want the editor version i.e. ProjectNameEditor Development Build.

And for this I suggest performing a rebuild by deleting your Binaries and Intermediate folders.

2 Likes

well that was an interesting solution, it solved 2 problems, and one was not the original problem, thanks

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms