top of page

VamPower

Platform
Engine
Language
Development Time
Team Size

PC
Unreal Engine
C++
4 Weeks

8

The Game:

Itch.io:

Your master, an imposing and sinister vampire overlord, has been vanquished in battle, yet he clings to life in his dark lair.

 

Armed with an array of formidable weapons, it is your duty to stand firm and protect your master’s heart from a relentless onslaught of bold heroes and desperate peasants.

These relentless attackers are determined to ensure his demise once and for all!

If you succeed in keeping your master alive amidst the chaos, he may reward your loyalty with a gift of unimaginable value—one truly worth "dying" for!

My Role

I was a AI & Gameplay Programmer.
My main responsibilities were:

  • AI

  • Behavior Trees

  • Behavior Tree Tasks

vampower.png

AI Base Classes & Inheritance

All of the AIs and the player were organized under different base classes to make it 

BP4.drawio.png

Behavior Tasks

Different AI behavior tree tasks that perform the AI actions in their behavior tree. From dashing away from the player, healing itself when hurt or attacking the player.

Chase Player

AI movement system that move the ai towards a location and activates walking animation if not active.

UBTTask_ChasePlayer.cpp

#include "BTTask_ChasePlayer.h"

#include "NPC_AIController.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Blueprint/AIBlueprintHelperLibrary.h"

UBTTask_ChasePlayer::UBTTask_ChasePlayer(FObjectInitializer const& ObjectInitializer)
{

   NodeName = TEXT("Chase Target");
}

EBTNodeResult::Type UBTTask_ChasePlayer::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
   //Get Character Controller
   if (auto* const AIController = Cast<ANPC_AIController>(OwnerComp.GetAIOwner()))
   {
       auto* const AICharacter = Cast<ABaseAI>(AIController->GetPawn());

        if (AICharacter->isWalking == false)
        {
           AICharacter->
AnimationWalkNotifer();
           AICharacter->
isWalking = true;
        }

       //Get Target Location from blackboard
       auto const TargetLocation = OwnerComp.GetBlackboardComponent()->GetValueAsVector(GetSelectedBlackboardKey());

       //Move to Target location
       UAIBlueprintHelperLibrary::SimpleMoveToLocation(AIController, TargetLocation);

       FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
       
return EBTNodeResult::Succeeded;
   }
       return EBTNodeResult::Failed;
}

 

UBTTask_ChasePlayer.cpp.h

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_ChasePlayer.generated.h"

/**

*/


UCLASS()
class GP4_GIT_API
UBTTask_ChasePlayer : public UBTTask_BlackboardBase
{
   
GENERATED_BODY()

public:
   
explicit UBTTask_ChasePlayer(FObjectInitializer const& ObjectInitializer);
   
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;

};

Dash

Propel the character towards or away from another character in a flexible strength

UBTTask_Dash.cpp

#include "BTTask_Dash.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "NPC_AIController.h"
#include "GameFramework/MovementComponent.h"
#include "GameFramework/PawnMovementComponent.h"
#include "BaseAI.h"

 

UBTTask_Dash::UBTTask_Dash(FObjectInitializer const& ObjectInitializer)
{
   
NodeName = TEXT("Dash");
}

EBTNodeResult::Type UBTTask_Dash::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{

    UObject* UTarget = OwnerComp.GetBlackboardComponent()->GetValueAsObject("TargetActor");

   if (auto* const ATarget = UTarget)
   {
       
AActor* TargetActor = Cast<AActor>(ATarget);
       
auto const* const AI = Cast<ANPC_AIController>(OwnerComp.GetAIOwner());
       
auto* const AIBase = Cast<ABaseAI>(AI->GetPawn());


       UPawnMovementComponent* MovementComponent = AI->GetPawn()->GetMovementComponent();
       
       
FVector Direction = TargetActor->GetActorLocation() - AI->GetPawn()->GetActorLocation();
       Direction.
Z = 0;

       float BackOrForward;
       AIBase->
AnimationDashNotifer();

       if (DashForward)
       {
           BackOrForward =
1;
       }
       
else if (!DashForward)
       {
           BackOrForward = -
1;
       }

       FVector ForceDircetion;
       ForceDircetion.
X = Direction.X * DashForce * BackOrForward;
       ForceDircetion.
Y = Direction.Y * DashForce * BackOrForward;

       MovementComponent->Velocity = ForceDircetion;

       FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
       
return EBTNodeResult::Type();
   }

  

   FinishLatentTask(OwnerComp, EBTNodeResult::Failed);
   
return EBTNodeResult::Type();
}

UBTTask_Dash.h

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_Dash.generated.h"

/**

*/


UCLASS()
class GP4_GIT_API
UBTTask_Dash : public UBTTask_BlackboardBase
{
   
GENERATED_BODY()
   

public:
   
explicit UBTTask_Dash(FObjectInitializer const& ObjectInitializer);
   
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;

   UPROPERTY(EditAnywhere, BlueprintReadOnly)
   
float DashForce = 10;

   UPROPERTY(EditAnywhere, BlueprintReadOnly)
   
bool DashForward;
};

Find Heart Location

Get a vector location in the navigation system in the radius of a specific StaticClass.

UBTTask_FindHeartLocation.cpp

#include "BTTask_FindHeartLocation.h"

#include "NavigationSystem.h"
#include "NPC_AIController.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Heart.h"
#include "Kismet/GameplayStatics.h"


UBTTask_FindHeartLocation::UBTTask_FindHeartLocation(FObjectInitializer const& ObjectInitializer)
{
   
NodeName = "Get Location of Heart";
}

EBTNodeResult::Type UBTTask_FindHeartLocation::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
   
if (auto* const Heart = UGameplayStatics::GetActorOfClass(GetWorld(), AHeart::StaticClass()))
   {

        auto const HeartLocation = Heart->GetActorLocation();


        if (SearchRadius)
       {
           
FNavLocation NavMeshLocation;

            //Generate random location near the player from the navigation system
            if (auto* const NavigationSystem = UNavigationSystemV1::GetCurrent(GetWorld()))
           {

                //Get the random location near player
                if (NavigationSystem->GetRandomPointInNavigableRadius(HeartLocation, SearchRadius, NavMeshLocation))
               {
                   OwnerComp.
GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(),      

                    NavMeshLocation.Location);


                    FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
                   
return EBTNodeResult::Succeeded;
               }
           }
       }
       
else
        {
           OwnerComp.
GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(), HeartLocation);


            FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
           
return EBTNodeResult::Succeeded;
       }
   }

    return EBTNodeResult::Failed;
}

UBTTask_FindHeartLocation.h

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_FindHeartLocation.generated.h"

 

/**

*/


UCLASS()
class GP4_GIT_API UBTTask_FindHeartLocation : public UBTTask_BlackboardBase
{
   
GENERATED_BODY()

public:
   
explicit UBTTask_FindHeartLocation(FObjectInitializer const& ObjectInitializer);
   
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;

    
   
UPROPERTY(EditAnywhere, BlueprintReadOnly)
   
float SearchRadius = 150.f;

 

};

Find Player Location

Get a vector location in the navigation system in the radius of the player.

UBTTask_FindPlayerLocation.cpp

#include "BTTask_FindPlayerLocation.h"

#include "NavigationSystem.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "GameFramework/Character.h"
#include "Kismet/GameplayStatics.h"

UBTTask_FindPlayerLocation::UBTTask_FindPlayerLocation(FObjectInitializer const& ObjectInitializer)
{
   
NodeName = TEXT("Find Player Location");
}

EBTNodeResult::Type UBTTask_FindPlayerLocation::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{

   //Get player
   if (auto* const Player = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0))
   {
       
auto const PlayerLocation = Player->GetActorLocation();


       if (SearchRadius)
       {
           
FNavLocation NavMeshLocation;

           //Generate random location near the player from the navigation system
           if (auto* const NavigationsSystem = UNavigationSystemV1::GetCurrent(GetWorld()))
           {

               //Get the random location near player
               if (NavigationsSystem->GetRandomPointInNavigableRadius(PlayerLocation, SearchRadius, NavMeshLocation))
               {

                   OwnerComp.GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(),                  

                   NavMeshLocation.Location);


                   FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
                   
return EBTNodeResult::Succeeded;
               }

           }
       }
       
else
       {
           OwnerComp.
GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(), PlayerLocation);


           FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
           
return EBTNodeResult::Succeeded;
       }
   }
   
   
return EBTNodeResult::Failed;
}

UBTTask_FindPlayerLocation.h

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_FindPlayerLocation.generated.h"

/**

*/


UCLASS()
class GP4_GIT_API UBTTask_FindPlayerLocation : public UBTTask_BlackboardBase
{
   
GENERATED_BODY()
   

public
   
explicit UBTTask_FindPlayerLocation(FObjectInitializer const& ObjectInitializer);
   
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;

   UPROPERTY(EditAnywhere, BlueprintReadWrite)
   
bool SearchRandom = false;

   UPROPERTY(EditAnywhere, BlueprintReadWrite)
   
float SearchRadius = 150.f;
};

Find Target Location

Get a vector location in the navigation system in the radius of a Blackboard UObject

UBTTask_FindTargetLocation.cpp

#include "BTTask_FindTargetLocation.h"
#include "NavigationSystem.h"
#include "BehaviorTree/BlackboardComponent.h"

UBTTask_FindTargetLocation::UBTTask_FindTargetLocation(FObjectInitializer const& ObjectInitializer)
{
   
NodeName = TEXT("Find Target Location");
}

EBTNodeResult::Type UBTTask_FindTargetLocation::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{

   UObject* UTarget = OwnerComp.GetBlackboardComponent()->GetValueAsObject("TargetActor");

   if (auto* const ATarget = UTarget)
   {
       
AActor* TargetActor = Cast<AActor>(ATarget);
       
auto const TargetActorLocation = TargetActor->GetActorLocation();


       if (SearchRadius)
       {
           
FNavLocation NavMeshLocation;

           //Generate random location near the player from the navigation system
           if (auto* const NavigationSystem = UNavigationSystemV1::GetCurrent(GetWorld()))
           {

                //Get the random location near player
               if (NavigationSystem->GetRandomPointInNavigableRadius(TargetActorLocation, SearchRadius, NavMeshLocation))
               {
                   OwnerComp.
GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(), 

                   NavMeshLocation.Location);


                   FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
                   
return EBTNodeResult::Succeeded;
               }
           }
       }
       
else
       {
           OwnerComp.
GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(), TargetActorLocation);


           FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
           
return EBTNodeResult::Succeeded;
       }
   }

    return EBTNodeResult::Failed;
}

UBTTask_FindTargetLocation.h

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_FindTargetLocation.generated.h"

/**

*/


UCLASS()
class GP4_GIT_API UBTTask_FindTargetLocation : public UBTTask_BlackboardBase
{
   
GENERATED_BODY()
   

public:
   
explicit UBTTask_FindTargetLocation(FObjectInitializer const& ObjectInitializer);
   
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;

   UPROPERTY(EditAnywhere, BlueprintReadWrite)
   
float SearchRadius = 150.f;
};

Get Starting Location

Get a vector location of the Character starting position.

UBTTask_GetStartingLocation.cpp

#include "BTTask_GetStartingLocation.h"
#include "AIController.h"
#include "BaseCharacter.h"
#include "Runtime/Engine/Classes/Engine/World.h"
#include "Engine/LatentActionManager.h"
#include "BehaviorTree/BlackboardComponent.h"

 

UBTTask_GetStartingLocation::UBTTask_GetStartingLocation(FObjectInitializer const& ObjectInitializer)
{
   
NodeName = TEXT("Get Starting Location");
}

EBTNodeResult::Type UBTTask_GetStartingLocation::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
   
auto const* const AI = OwnerComp.GetAIOwner();
   
auto* const AICharacter = Cast<ABaseCharacter>(AI->GetPawn());
   
FVector CharacterStartingLocation = AICharacter->StartingLocation;

    
   OwnerComp.
GetBlackboardComponent()->SetValueAsVector(GetSelectedBlackboardKey(), CharacterStartingLocation);


    FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
   
return EBTNodeResult::Succeeded;
}

UBTTask_GetStartingLocation.h

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_GetStartingLocation.generated.h"

/**

*/


UCLASS()
class GP4_GIT_API UBTTask_GetStartingLocation : public UBTTask_BlackboardBase
{
   
GENERATED_BODY()
   

public:
   
explicit UBTTask_GetStartingLocation(FObjectInitializer const& ObjectInitializer);
   
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
};

Heal

Heal the Character by the Characters healing amount.

UBTTask_Heal.cpp

#include "BTTask_Heal.h"
#include "AIController.h"
#include "Runtime/Engine/Classes/Engine/World.h"
#include "Engine/LatentActionManager.h"
#include "BehaviorTree/BlackboardComponent.h"


UBTTask_Heal::UBTTask_Heal()
{
   
NodeName = TEXT("Heal Own Character");
}

EBTNodeResult::Type UBTTask_Heal::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
   
auto const* const AI = OwnerComp.GetAIOwner();

   auto* const AIEnemy= Cast<ABaseEnemy>(AI->GetPawn());
   AIEnemy->
HealthComponent->HealCharacter(AIEnemy->HealthComponent->HealAmount);


   FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
   return EBTNodeResult::Type();
}

UBTTask_Heal.h

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_Heal.generated.h"

/**

*/


UCLASS()
class GP4_GIT_API UBTTask_Heal : public UBTTask_BlackboardBase
{
   
GENERATED_BODY()

public:

   UBTTask_Heal();
   
EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;

   
};

Melee Attack

Attacking the character dealing damage depending on own character with a cooldown.

UBTTask_MeleeAttack.cpp

#include "BTTask_MeleeAttack.h"
#include "AIController.h"
#include "BaseAI.h"
#include "Runtime/Engine/Classes/Engine/World.h"
#include "Engine/LatentActionManager.h"
#include "BehaviorTree/BlackboardComponent.h"

UBTTask_MeleeAttack::UBTTask_MeleeAttack()
{
   
NodeName = TEXT("Melee Attack");
}

EBTNodeResult::Type UBTTask_MeleeAttack::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
   
auto const OutOfRange = !OwnerComp.GetBlackboardComponent()->GetValueAsBool(GetSelectedBlackboardKey());

   if (OutOfRange)
   {

       //If not in range then finnish attack without damaging
       bWindup = true;
       
bMeleeCooldown = false;

       FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
       
return EBTNodeResult::Succeeded;
   }


   //If we are in range then get the ai character
   auto const* const AI = OwnerComp.GetAIOwner();
   
auto* const AICharacter = Cast<ABaseAI>(AI->GetPawn());


   if (bMeleeCooldown)
   {
       AICharacter->
StartMeleeAttack(AICharacter->MeleeCooldown);

       bMeleeCooldown = false;

       FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
       
return EBTNodeResult::Succeeded;
   }


   if (AICharacter->isPossibleToMeleeAttack == true && bWindup)
   {
       AICharacter->
isPossibleToMeleeAttack = false;
       
bWindup = false;

       AICharacter->AnimationMeleeAttackWindupNotifer();
       AICharacter->
StartMeleeAttack(AICharacter->MeleeDelay);
       AICharacter->
isWalking = false;

       FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
       
return EBTNodeResult::Succeeded;
   }


   UObject* UTarget = OwnerComp.GetBlackboardComponent()->GetValueAsObject("TargetActor");
   
auto* const ATarget = UTarget;

   if (ATarget)
   {

       AActor* TargetActor = AICharacter->ParentTarget;
       
ABaseCharacter* TargetBaseCharacter = Cast<ABaseCharacter>(TargetActor);

       if (TargetBaseCharacter && AICharacter->isPossibleToMeleeAttack && OutOfRange == false)
       {

           
           
bMeleeCooldown = AICharacter->isPossibleToMeleeAttack;
           
bWindup = AICharacter->isPossibleToMeleeAttack;

           AICharacter->isPossibleToMeleeAttack = false;
           
            
           TargetBaseCharacter->
HealthComponent->TakeDamage(AICharacter->FinalAttackDamage);

           AICharacter->AnimationMeleeAttackNotifer();
           AICharacter->
isWalking = false;


           FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
           
return EBTNodeResult::Type();
       }
   }


   FinishLatentTask(OwnerComp, EBTNodeResult::Failed);
   
return EBTNodeResult::Type();

}

UBTTask_MeleeAttack.h

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_MeleeAttack.generated.h"

/**

*/


UCLASS()
class GP4_GIT_API UBTTask_MeleeAttack : public UBTTask_BlackboardBase
{
   
GENERATED_BODY()

public:

   UBTTask_MeleeAttack();
   
EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
   

private:

   UPROPERTY(EditDefaultsOnly)
   
bool bWindup = true;

   UPROPERTY(EditDefaultsOnly)
   
bool bMeleeCooldown = false;

};

Range Attack

Create a projectile at predetermined location on the character blueprint.

UBTTask_RangeAttack.cpp

#include "BTTask_RangeAttack.h"
#include "AIController.h"
#include "Runtime/Engine/Classes/Engine/World.h"
#include "Engine/LatentActionManager.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Projectile.h"
#include "BaseCharacter.h"
#include "BaseAI.h"

 

UBTTask_RangeAttack::UBTTask_RangeAttack()
{
   
NodeName = TEXT("Range Attack");
}

EBTNodeResult::Type UBTTask_RangeAttack::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
   
auto const OutOfRange = !OwnerComp.GetBlackboardComponent()->GetValueAsBool(GetSelectedBlackboardKey());


   if (OutOfRange)
   {

       //If not in range then finnish attack without damaging
       FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
       
return EBTNodeResult::Type();
   }

   //If we are in range then get the ai character
   auto const* const AI = OwnerComp.GetAIOwner();


   auto* const AIBase = Cast<ABaseAI>(AI->GetPawn());
   AIBase->
AnimationRangeAttackNotifer();

   AProjectile* projectile;

   FActorSpawnParameters parameters;
   parameters.
Owner = AI->GetPawn();


   projectile = GetWorld()->SpawnActor<AProjectile>(
       AIBase->
ProjectileSubClass,
       AIBase->
ProjectileSpawnPosition->GetComponentLocation(),
       AIBase->
ProjectileSpawnPosition->GetComponentRotation(),
       parameters

    );

   FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
   
return EBTNodeResult::Type();
}

UBTTask_RangeAttack.h

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_RangeAttack.generated.h"

class AProjectile;
/**

*/


UCLASS()
class GP4_GIT_API UBTTask_RangeAttack : public UBTTask_BlackboardBase
{
   
GENERATED_BODY()
   

public:

    UBTTask_RangeAttack();
   
EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
};

Range Attack

Create projectiles in an arch around a predetermined location on the character blueprint.

UBTTask_MultiRangeAttack.cpp

#include "BTTask_MultiRangeAttack.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "AIController.h"
#include "ProjectileAOE.h"
#include "BaseCharacter.h"
#include "BaseAI.h"

 

UBTTask_MultiRangeAttack::UBTTask_MultiRangeAttack()
{
   
NodeName = TEXT("Multi Range Attack");
}

EBTNodeResult::Type UBTTask_MultiRangeAttack::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
   
auto const OutOfRange = !OwnerComp.GetBlackboardComponent()->GetValueAsBool(GetSelectedBlackboardKey());


   if (OutOfRange)
   {

       //If not in range then finnish attack without damaging
       FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
       
return EBTNodeResult::Succeeded;
   }

   //If we are in range then get the ai character
   auto const* const AI = OwnerComp.GetAIOwner();

   AProjectileAOE* projectile;
   
auto* const AIBaseCharacter = Cast<ABaseCharacter>(AI->GetPawn());
   
auto* const AIBase = Cast<ABaseAI>(AI->GetPawn());

   AIBase->AnimationRangeAttackNotifer();

   FActorSpawnParameters parameters;
   parameters.
Owner = AI->GetPawn();

    
   
for (auto i = 0; i < NrOfProjectiles; i++)
   {
       
FRotator Rotation = AIBaseCharacter->ProjectileSpawnPosition->GetComponentRotation();
       
int32 RoationIncrease = 5 * i;
       
int32 RoationDecrease = 5 * NrOfProjectiles / 2;
       
int32 Roation = Rotation.Yaw + RoationIncrease - RoationDecrease;

       Rotation.Yaw = Roation;

       projectile = GetWorld()->SpawnActor<AProjectileAOE>(
           AIBaseCharacter->
AOEProjectileSubClass,
           AIBaseCharacter->
ProjectileSpawnPosition->GetComponentLocation(),
           Rotation,
           parameters

        );
   }

   FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
   
return EBTNodeResult::Type();
}

UBTTask_MultiRangeAttack.h

#pragma once

#include "CoreMinimal.h"
#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h"
#include "BTTask_MultiRangeAttack.generated.h"

/**

*/


UCLASS()
class GP4_GIT_API UBTTask_MultiRangeAttack : public UBTTask_BlackboardBase
{
   
GENERATED_BODY()

public:
   
UBTTask_MultiRangeAttack();
   
EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
   
   
UPROPERTY(EditAnywhere, BlueprintReadOnly)
   
int32 NrOfProjectiles = 5;
};

Behavior Trees

All the AIs incorporate a behavior tree that outlines a sequence of tasks and conditions. 

BP42.drawio.png

Range Ally

Range Ally

Range Ally.PNG

Melee Ally

MeleeAlly.PNG

Melee Enemy

GP4MeleeEnemy.PNG

Range Enemy

RangeEnemy.PNG

Boss

Miscellaneous (Blueprints)

Blueprint that calculates an arc towards the ai:s target to launch a projectile towards.

Blueprint

Projectile Launching

Projectile.PNG

Contact me

070 415 20 61

Stockholm, Sweden

bottom of page