diff --git a/Content/Enemy/BB_Base_Enemy.uasset b/Content/Enemy/BB_Base_Enemy.uasset new file mode 100644 index 0000000..4754676 --- /dev/null +++ b/Content/Enemy/BB_Base_Enemy.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d05342d401b4b8dc0c3e28fb9a9169cc305b78b1029be1d7f5d85d0d45c1014 +size 5253 diff --git a/Content/Enemy/BehaviorTrees/BT_Attacking_State.uasset b/Content/Enemy/BehaviorTrees/BT_Attacking_State.uasset new file mode 100644 index 0000000..17616be --- /dev/null +++ b/Content/Enemy/BehaviorTrees/BT_Attacking_State.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4aa6120a1019fa9a70169fd1bc87de566e9653df822c5d17d9043276c567e2f +size 29454 diff --git a/Content/Enemy/BehaviorTrees/BT_Find_Cover.uasset b/Content/Enemy/BehaviorTrees/BT_Find_Cover.uasset new file mode 100644 index 0000000..8a9e2d0 --- /dev/null +++ b/Content/Enemy/BehaviorTrees/BT_Find_Cover.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8ae5b944c94321fc570d414fea297adbe0fa0d5a1998fa76579a61fd8a73e5f +size 11351 diff --git a/Content/Enemy/BehaviorTrees/BT_Fire_Weapon.uasset b/Content/Enemy/BehaviorTrees/BT_Fire_Weapon.uasset new file mode 100644 index 0000000..6389b51 --- /dev/null +++ b/Content/Enemy/BehaviorTrees/BT_Fire_Weapon.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa0777bdb6070ed25054cc1d38888df0aaa066ce499fdea01c556ee322156f43 +size 8261 diff --git a/Content/Enemy/BehaviorTrees/BT_Investigating_State.uasset b/Content/Enemy/BehaviorTrees/BT_Investigating_State.uasset new file mode 100644 index 0000000..5fe29e8 --- /dev/null +++ b/Content/Enemy/BehaviorTrees/BT_Investigating_State.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:167d55cce0fcf3684613917077949dd2e922a6cfd46014b4492926e59de0bbac +size 10806 diff --git a/Content/Enemy/BehaviorTrees/BT_Passive_State.uasset b/Content/Enemy/BehaviorTrees/BT_Passive_State.uasset new file mode 100644 index 0000000..809608d --- /dev/null +++ b/Content/Enemy/BehaviorTrees/BT_Passive_State.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db3c0d6c6178ee434cddbaf740563546f7b3c78655dea35c0e5bd8f77d1a0233 +size 20074 diff --git a/Content/Enemy/EQS/AttackTarget.uasset b/Content/Enemy/EQS/AttackTarget.uasset new file mode 100644 index 0000000..e25ef2e --- /dev/null +++ b/Content/Enemy/EQS/AttackTarget.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c301262f435afa726497425b119c5f5aab80501dd20bee5476a7cfa4dcf4ba3a +size 31452 diff --git a/Content/Enemy/EQS/EQSTestingPawn.uasset b/Content/Enemy/EQS/EQSTestingPawn.uasset new file mode 100644 index 0000000..21c2b67 --- /dev/null +++ b/Content/Enemy/EQS/EQSTestingPawn.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f3eebdb5c3e64b80dc9608a0de79f2f858198226723623675371ef87cc814c46 +size 23202 diff --git a/Content/Enemy/EQS/EQS_FindCover.uasset b/Content/Enemy/EQS/EQS_FindCover.uasset new file mode 100644 index 0000000..6d0efcc --- /dev/null +++ b/Content/Enemy/EQS/EQS_FindCover.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f4fac65c93b0a643e3897612c0d8aad0090cf3e1708e62701829f5622a164ba +size 7182 diff --git a/Content/Enemy/EQS/EQS_FindIdealRange.uasset b/Content/Enemy/EQS/EQS_FindIdealRange.uasset new file mode 100644 index 0000000..efb8de4 --- /dev/null +++ b/Content/Enemy/EQS/EQS_FindIdealRange.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:69da4619195e312747cc99b0a65cebe3cb6dba7cff6d7f85d65a5bf630b177a6 +size 9598 diff --git a/Content/Enemy/EQS/EQS_Strafe.uasset b/Content/Enemy/EQS/EQS_Strafe.uasset new file mode 100644 index 0000000..85cba39 --- /dev/null +++ b/Content/Enemy/EQS/EQS_Strafe.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c52d3a813cb2ace15d022913f6085d367cc4330b26c92f3c36520496121a5026 +size 7010 diff --git a/Content/Enemy/FireWeaponTasks.uasset b/Content/Enemy/FireWeaponTasks.uasset deleted file mode 100644 index bb06c91..0000000 --- a/Content/Enemy/FireWeaponTasks.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2d62b5fd4bffcbd1b1a9a8ce534518cf789216991f050a3481103f11c4313dbb -size 9411 diff --git a/Content/Enemy/Tasks/BTTMoveToIdealRange.uasset b/Content/Enemy/Tasks/BTTMoveToIdealRange.uasset new file mode 100644 index 0000000..5997afe --- /dev/null +++ b/Content/Enemy/Tasks/BTTMoveToIdealRange.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35f6fe1f6c16f3a0920d3bfdfdedbfad5067979f25239d8a13df1a942305824b +size 40726 diff --git a/Content/Enemy/Worker/AIC_Worker.uasset b/Content/Enemy/Worker/AIC_Worker.uasset new file mode 100644 index 0000000..517c5f0 --- /dev/null +++ b/Content/Enemy/Worker/AIC_Worker.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eabfe5d0b7d9fb24fd797f5ab6c6b16b90c2dcdfd1d630b7f62645bec170d357 +size 20894 diff --git a/Content/Enemy/Worker/BB_Worker.uasset b/Content/Enemy/Worker/BB_Worker.uasset deleted file mode 100644 index 9ee8152..0000000 --- a/Content/Enemy/Worker/BB_Worker.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0389d49e48e76a626f19b5cb173168d2eb0dff74a6ba6a1db4ed6149f75b4ca7 -size 3379 diff --git a/Content/Enemy/Worker/BT_Worker.uasset b/Content/Enemy/Worker/BT_Worker.uasset index 5f426cf..2727938 100644 --- a/Content/Enemy/Worker/BT_Worker.uasset +++ b/Content/Enemy/Worker/BT_Worker.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96c2010017f544db0377a648fb78e655ffd93953f5adf4a6c78d32415e4f1e68 -size 35454 +oid sha256:1aa0439b160b9cc4a744f2efdbb6131ffeb1aec8a50685dea2f921cae8be614e +size 33660 diff --git a/Content/Enemy/Worker/C_Worker.uasset b/Content/Enemy/Worker/C_Worker.uasset index 22843bf..cdcd13d 100644 --- a/Content/Enemy/Worker/C_Worker.uasset +++ b/Content/Enemy/Worker/C_Worker.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc57648ca59ab9181814d46afa44701b6ab3dd1d1114d60963cda8729b1aee7c -size 40112 +oid sha256:1307c6303ccede36903875211f758077933ef495e0fb8aebe8c45147e9cfb66d +size 38588 diff --git a/Content/Levels/TestLevel.umap b/Content/Levels/TestLevel.umap index 00bb672..c9de13a 100644 --- a/Content/Levels/TestLevel.umap +++ b/Content/Levels/TestLevel.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2982149907d00efe6509ec3e0258f31442fedeb988fd15132f604413a0de1a1c -size 47583 +oid sha256:26a15ae4ce8cbab7bc63b8abb00075551a55cae73ce5434bd8c0a8446be1ee95 +size 77030 diff --git a/Content/TestPatrolRoute.uasset b/Content/TestPatrolRoute.uasset new file mode 100644 index 0000000..2657dd9 --- /dev/null +++ b/Content/TestPatrolRoute.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:951fb0bbfcbd6e594c596168e3247eaa4db8ab4f8237e5f965540c1ecd01add9 +size 20989 diff --git a/Content/Weapons/Pistol/Pistol.uasset b/Content/Weapons/Pistol/Pistol.uasset index 5959a19..7c06c57 100644 --- a/Content/Weapons/Pistol/Pistol.uasset +++ b/Content/Weapons/Pistol/Pistol.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b97899ccc443870d47aa50df9974339e0487633ebcc22d6b2b884292ea266ca2 +oid sha256:42b20fafef19a1ca1ce6b3a428f4dc5c358054ef427e00862851aa48895a8ebe size 22640 diff --git a/Source/Nakatomi/Decorators/BTDCanSeeTarget.cpp b/Source/Nakatomi/Decorators/BTDCanSeeTarget.cpp new file mode 100644 index 0000000..75302e2 --- /dev/null +++ b/Source/Nakatomi/Decorators/BTDCanSeeTarget.cpp @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "../Decorators/BTDCanSeeTarget.h" + +#include "AIController.h" +#include "BehaviorTree/BlackboardComponent.h" + +bool UBTDCanSeeTarget::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const +{ + FHitResult HitResult; + + FVector Start = OwnerComp.GetAIOwner()->GetPawn()->GetActorLocation(); + + UBlackboardComponent* BlackboardComponent = OwnerComp.GetBlackboardComponent(); + AActor* TargetActor = Cast(BlackboardComponent->GetValueAsObject(TargetActorKey.SelectedKeyName)); + FVector End = TargetActor->GetActorLocation(); + + GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, ECC_Pawn); + + if (HitResult.GetActor()) + { + return true; + } + + return false; +} diff --git a/Source/Nakatomi/Decorators/BTDCanSeeTarget.h b/Source/Nakatomi/Decorators/BTDCanSeeTarget.h new file mode 100644 index 0000000..e926c3b --- /dev/null +++ b/Source/Nakatomi/Decorators/BTDCanSeeTarget.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTDecorator.h" +#include "BTDCanSeeTarget.generated.h" + +/** + * + */ +UCLASS() +class NAKATOMI_API UBTDCanSeeTarget : public UBTDecorator +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, Category = "Options", + Meta = (AllowPrivateAccess = "true", DisplayName = "Target Actor Key")) + FBlackboardKeySelector TargetActorKey; + +protected: + virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override; +}; diff --git a/Source/Nakatomi/Decorators/BTDHasPatrolRoute.cpp b/Source/Nakatomi/Decorators/BTDHasPatrolRoute.cpp new file mode 100644 index 0000000..9345c29 --- /dev/null +++ b/Source/Nakatomi/Decorators/BTDHasPatrolRoute.cpp @@ -0,0 +1,14 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "../Decorators/BTDHasPatrolRoute.h" + +#include "Nakatomi/EnemyAIController.h" + +bool UBTDHasPatrolRoute::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const +{ + AEnemyAIController* enemyController = Cast(OwnerComp.GetAIOwner()); + AEnemyCharacter* enemyPawn = Cast(enemyController->GetPawn()); + + return enemyPawn->CurrentPatrolRoute ? true : false; +} diff --git a/Source/Nakatomi/Decorators/BTDHasPatrolRoute.h b/Source/Nakatomi/Decorators/BTDHasPatrolRoute.h new file mode 100644 index 0000000..c9cc9bd --- /dev/null +++ b/Source/Nakatomi/Decorators/BTDHasPatrolRoute.h @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTDecorator.h" +#include "BTDHasPatrolRoute.generated.h" + +/** + * + */ +UCLASS(Blueprintable) +class NAKATOMI_API UBTDHasPatrolRoute : public UBTDecorator +{ + GENERATED_BODY() + +public: + virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override; +}; diff --git a/Source/Nakatomi/Decorators/BTDIsHealthBelowThreshold.cpp b/Source/Nakatomi/Decorators/BTDIsHealthBelowThreshold.cpp new file mode 100644 index 0000000..6e21503 --- /dev/null +++ b/Source/Nakatomi/Decorators/BTDIsHealthBelowThreshold.cpp @@ -0,0 +1,14 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "../Decorators/BTDIsHealthBelowThreshold.h" + +#include "BehaviorTree/BlackboardComponent.h" + +bool UBTDIsHealthBelowThreshold::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const +{ + UBlackboardComponent* BlackboardComponent = OwnerComp.GetBlackboardComponent(); + float currentHealth = BlackboardComponent->GetValueAsFloat(CurrentHealthKey.SelectedKeyName); + + return currentHealth <= HealthThreshold ? true : false; +} diff --git a/Source/Nakatomi/Decorators/BTDIsHealthBelowThreshold.h b/Source/Nakatomi/Decorators/BTDIsHealthBelowThreshold.h new file mode 100644 index 0000000..a65081d --- /dev/null +++ b/Source/Nakatomi/Decorators/BTDIsHealthBelowThreshold.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTDecorator.h" +#include "BTDIsHealthBelowThreshold.generated.h" + +/** + * + */ +UCLASS() +class NAKATOMI_API UBTDIsHealthBelowThreshold : public UBTDecorator +{ + GENERATED_BODY() + +public: + + UPROPERTY(EditAnywhere, Category = "Options", + Meta = (AllowPrivateAccess = "true", DisplayName = "Current Health Key")) + FBlackboardKeySelector CurrentHealthKey; + + UPROPERTY(EditAnywhere, Category = "Options", + Meta = (AllowPrivateAccess = "true", DisplayName = "Health Threshold")) + float HealthThreshold = 25.0f; + +protected: + virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override; +}; diff --git a/Source/Nakatomi/Decorators/BTDIsWithinRange.cpp b/Source/Nakatomi/Decorators/BTDIsWithinRange.cpp new file mode 100644 index 0000000..53328ce --- /dev/null +++ b/Source/Nakatomi/Decorators/BTDIsWithinRange.cpp @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "../Decorators/BTDIsWithinRange.h" + +#include "AIController.h" +#include "navigationSystem.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "Nakatomi/NakatomiCharacter.h" + +bool UBTDIsWithinRange::CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const +{ + UBlackboardComponent* BlackboardComponent = OwnerComp.GetBlackboardComponent(); + float Dist = BlackboardComponent->GetValueAsFloat(DistanceKey.SelectedKeyName); + UObject* Target = BlackboardComponent->GetValueAsObject(TargetActorKey.SelectedKeyName); + auto TargetLocation = Cast(Target)->GetActorLocation(); + UNavigationSystemV1* NavigationSystem = FNavigationSystem::GetCurrent(GetWorld()); + + APawn* pawn = OwnerComp.GetAIOwner()->GetPawn(); + + if (pawn && NavigationSystem && TargetLocation != FVector::ZeroVector) + { + double Distance = -1.0; + NavigationSystem->GetPathLength(TargetLocation, pawn->GetTransform().GetLocation(), Distance); + return Distance <= Dist ? true : false; + } + + return false; +} diff --git a/Source/Nakatomi/Decorators/BTDIsWithinRange.h b/Source/Nakatomi/Decorators/BTDIsWithinRange.h new file mode 100644 index 0000000..dce4bc0 --- /dev/null +++ b/Source/Nakatomi/Decorators/BTDIsWithinRange.h @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTDecorator.h" +#include "BTDIsWithinRange.generated.h" + +/** + * + */ +UCLASS() +class NAKATOMI_API UBTDIsWithinRange : public UBTDecorator +{ + GENERATED_BODY() + +public: + + UPROPERTY(EditAnywhere, Category = "Options", + Meta = (AllowPrivateAccess = "true", DisplayName = "Target Actor Key")) + FBlackboardKeySelector TargetActorKey; + + UPROPERTY(EditAnywhere, Category = "Options", + Meta = (AllowPrivateAccess = "true", DisplayName = "Distance Key")) + FBlackboardKeySelector DistanceKey; + +public: + + virtual bool CalculateRawConditionValue(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) const override; + +}; diff --git a/Source/Nakatomi/Decorators/BTDWeaponCooldown.cpp b/Source/Nakatomi/Decorators/BTDWeaponCooldown.cpp new file mode 100644 index 0000000..3855d0b --- /dev/null +++ b/Source/Nakatomi/Decorators/BTDWeaponCooldown.cpp @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "../Decorators/BTDWeaponCooldown.h" + +#include "AIController.h" +#include "Nakatomi/EnemyCharacter.h" + +void UBTDWeaponCooldown::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) +{ + AEnemyCharacter* EnemyCharacter = Cast(OwnerComp.GetAIOwner()->GetPawn()); + + if (EnemyCharacter && EnemyCharacter->GetCurrentWeapon()) + { + const float Cooldown = EnemyCharacter->GetCurrentWeapon()->GetWeaponProperties()->WeaponCooldown; + if (CoolDownTime != Cooldown) + { + CoolDownTime = Cooldown; + } + } + + Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds); +} diff --git a/Source/Nakatomi/Decorators/BTDWeaponCooldown.h b/Source/Nakatomi/Decorators/BTDWeaponCooldown.h new file mode 100644 index 0000000..5367200 --- /dev/null +++ b/Source/Nakatomi/Decorators/BTDWeaponCooldown.h @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/Decorators/BTDecorator_Cooldown.h" +#include "BTDWeaponCooldown.generated.h" + +/** + * + */ +UCLASS() +class NAKATOMI_API UBTDWeaponCooldown : public UBTDecorator_Cooldown +{ + GENERATED_BODY() + +protected: + virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override; +}; diff --git a/Source/Nakatomi/EAIState.cpp b/Source/Nakatomi/EAIState.cpp new file mode 100644 index 0000000..b94b964 --- /dev/null +++ b/Source/Nakatomi/EAIState.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "EAIState.h" + diff --git a/Source/Nakatomi/EAIState.h b/Source/Nakatomi/EAIState.h new file mode 100644 index 0000000..abadf5b --- /dev/null +++ b/Source/Nakatomi/EAIState.h @@ -0,0 +1,18 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + +/** + * + */ +UENUM(BlueprintType) +enum class EAIState : uint8 +{ + PASSIVE UMETA(DisplayName = "Passive"), + ATTACKING UMETA(DisplayName = "Attacking"), + FROZEN UMETA(DisplayName = "Frozen"), + INVESTIGATING UMETA(DisplayName = "Investigating"), + DEAD UMETA(DisplayName = "Dead"), +}; diff --git a/Source/Nakatomi/EPatrolMovementEnum.cpp b/Source/Nakatomi/EPatrolMovementEnum.cpp new file mode 100644 index 0000000..f50c7ad --- /dev/null +++ b/Source/Nakatomi/EPatrolMovementEnum.cpp @@ -0,0 +1,4 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "EPatrolMovementEnum.h" diff --git a/Source/Nakatomi/EPatrolMovementEnum.h b/Source/Nakatomi/EPatrolMovementEnum.h new file mode 100644 index 0000000..86797f1 --- /dev/null +++ b/Source/Nakatomi/EPatrolMovementEnum.h @@ -0,0 +1,16 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + +/** + * + */ +UENUM(BlueprintType) +enum class EPatrolMovementEnum : uint8 +{ + SLOWWALK UMETA(DisplayName = "Slow Walk"), + WALK UMETA(DisplayName = "Walk"), + SPRINT UMETA(DisplayName = "Sprint"), +}; diff --git a/Source/Nakatomi/EnemyAIController.cpp b/Source/Nakatomi/EnemyAIController.cpp index bbc8b5a..259e413 100644 --- a/Source/Nakatomi/EnemyAIController.cpp +++ b/Source/Nakatomi/EnemyAIController.cpp @@ -2,6 +2,8 @@ #include "EnemyAIController.h" #include + +#include "EAIState.h" #include "NakatomiGameInstance.h" #include "BehaviorTree/BehaviorTree.h" #include "BehaviorTree/BlackboardComponent.h" @@ -25,8 +27,19 @@ AEnemyAIController::AEnemyAIController(const FObjectInitializer& object_initiali SightConfig->DetectionByAffiliation.bDetectEnemies = true; SightConfig->DetectionByAffiliation.bDetectNeutrals = true; + HearingConfig = CreateDefaultSubobject(TEXT("Hearing Sense Config")); + HearingConfig->HearingRange = 800.0f; + HearingConfig->SetMaxAge(3.0f); + HearingConfig->DetectionByAffiliation.bDetectEnemies = true; + HearingConfig->DetectionByAffiliation.bDetectNeutrals = true; + + DamageConfig = CreateDefaultSubobject(TEXT("Damage Sense Config")); + DamageConfig->SetMaxAge(5.0f); + AIPerception->SetDominantSense(SightConfig->GetSenseImplementation()); AIPerception->ConfigureSense(*SightConfig); + AIPerception->ConfigureSense(*HearingConfig); + AIPerception->ConfigureSense(*DamageConfig); } void AEnemyAIController::OnPossess(APawn* InPawn) @@ -48,6 +61,11 @@ void AEnemyAIController::OnPossess(APawn* InPawn) BehaviorTree->StartTree(*behaviourTree); Blackboard->SetValueAsObject("SelfActor", enemy); } + + Blackboard->SetValueAsEnum("State", static_cast(EAIState::PASSIVE)); + + Blackboard->SetValueAsFloat("AttackRadius", enemy->AttackRadius); + Blackboard->SetValueAsFloat("DefendRadius", enemy->DefendRadius); //ensure(enemy->GetMovementComponent()->UseAccelerationForPathFollowing()); } @@ -116,7 +134,7 @@ void AEnemyAIController::OnDeath(FDamageInfo info) void AEnemyAIController::OnPerceptionUpdated(const TArray& actors) { - for (auto actor : actors) + for (AActor* actor : actors) { if (!actor->GetClass()->IsChildOf(APlayerCharacter::StaticClass())) { @@ -126,13 +144,46 @@ void AEnemyAIController::OnPerceptionUpdated(const TArray& actors) FActorPerceptionBlueprintInfo perceptionInfo; PerceptionComponent->GetActorsPerception(actor, perceptionInfo); - for (auto& stimulus : perceptionInfo.LastSensedStimuli) + for (FAIStimulus& stimulus : perceptionInfo.LastSensedStimuli) { - if (!stimulus.IsValid() || stimulus.IsExpired()) + if (!stimulus.IsValid() || stimulus.IsExpired() || + static_cast(Blackboard->GetValueAsEnum("State")) == EAIState::DEAD) { continue; } + FAISenseID SightID; + FAISenseID HearingID; + FAISenseID DamageID; + + if (SightConfig) + { + SightID = SightConfig->GetSenseID(); + } + + if (HearingConfig) + { + HearingID = HearingConfig->GetSenseID(); + } + + if (DamageConfig) + { + DamageID = DamageConfig->GetSenseID(); + } + + if (stimulus.Type == SightID) + { + SensedSight(actor, stimulus); + } + else if (stimulus.Type == HearingID) + { + SensedHearing(actor, stimulus); + } + else if (stimulus.Type == DamageID) + { + SensedDamaged(actor, stimulus); + } + Blackboard->SetValueAsObject("TargetActor", actor); if (stimulus.IsActive()) @@ -179,3 +230,51 @@ bool AEnemyAIController::GetHasAttackToken() { return HasAttackToken; } + +void AEnemyAIController::SetState(EAIState state) +{ + Blackboard->SetValueAsEnum("State", static_cast(state)); +} + +void AEnemyAIController::SetStateAsPassive() +{ + SetState(EAIState::PASSIVE); +} + +void AEnemyAIController::SetStateAsAttacking(AActor* target) +{ + Blackboard->SetValueAsObject("TargetActor", target); + SetState(EAIState::ATTACKING); +} + +AActor* AEnemyAIController::GetTargetActor() +{ + return Cast(Blackboard->GetValueAsObject("TargetActor")); +} + +void AEnemyAIController::SensedSight(AActor* actor, FAIStimulus& stimulus) +{ + EAIState CurrentState = static_cast(Blackboard->GetValueAsEnum("State")); + + + if (CurrentState == EAIState::PASSIVE || CurrentState == EAIState::INVESTIGATING) + { + SetStateAsAttacking(actor); + } +} + +void AEnemyAIController::SensedHearing(AActor* actor, FAIStimulus& stimulus) +{ + EAIState CurrentState = static_cast(Blackboard->GetValueAsEnum("State")); + + if (CurrentState == EAIState::PASSIVE || CurrentState == EAIState::INVESTIGATING) + { + SetState(EAIState::INVESTIGATING); + Blackboard->SetValueAsVector("InvestigationLocation", stimulus.StimulusLocation); + } +} + +void AEnemyAIController::SensedDamaged(AActor* actor, FAIStimulus& stimulus) +{ + SetStateAsAttacking(actor); +} diff --git a/Source/Nakatomi/EnemyAIController.h b/Source/Nakatomi/EnemyAIController.h index 3122437..2e46abd 100644 --- a/Source/Nakatomi/EnemyAIController.h +++ b/Source/Nakatomi/EnemyAIController.h @@ -4,8 +4,11 @@ #include "CoreMinimal.h" #include "AIController.h" +#include "EAIState.h" #include "EnemyCharacter.h" #include "PlayerCharacter.h" +#include "Perception/AISenseConfig_Damage.h" +#include "Perception/AISenseConfig_Hearing.h" #include "Perception/AISenseConfig_Sight.h" #include "EnemyAIController.generated.h" @@ -29,6 +32,10 @@ private: UAISenseConfig_Sight* SightConfig; + UAISenseConfig_Hearing* HearingConfig; + + UAISenseConfig_Damage* DamageConfig; + bool HasAttackToken = false; public: @@ -59,4 +66,24 @@ public: UFUNCTION() bool GetHasAttackToken(); + + UFUNCTION() + void SetState(EAIState state); + + UFUNCTION() + void SetStateAsPassive(); + + UFUNCTION() + void SetStateAsAttacking(AActor* target); + + UFUNCTION(BlueprintCallable) + AActor* GetTargetActor(); + +private: + + void SensedSight(AActor* actor, FAIStimulus& stimulus); + + void SensedHearing(AActor* actor, FAIStimulus& stimulus); + + void SensedDamaged(AActor* actor, FAIStimulus& stimulus); }; diff --git a/Source/Nakatomi/EnemyCharacter.cpp b/Source/Nakatomi/EnemyCharacter.cpp index 41bf8bb..b23e46f 100644 --- a/Source/Nakatomi/EnemyCharacter.cpp +++ b/Source/Nakatomi/EnemyCharacter.cpp @@ -2,7 +2,11 @@ #include "EnemyCharacter.h" #include "EnemyAIController.h" +#include "EnemyHealthComponent.h" #include "InteractableComponent.h" +#include "BehaviorTree/BehaviorTree.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "BehaviorTree/BlackboardData.h" #define COLLISION_WEAPON ECC_GameTraceChannel1 @@ -10,8 +14,12 @@ AEnemyCharacter::AEnemyCharacter(const FObjectInitializer& ObjectInitializer) : { RandomWeaponParameters = CreateDefaultSubobject(TEXT("Random Weapon Parameters")); + auto healthComponent = CreateDefaultSubobject(TEXT("Health Component")); + SetHealthComponent(healthComponent); + GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged"); + GetHealthComponent()->OnDeath.BindUFunction(this, "OnDeath"); GetHealthComponent()->SetMaxHealth(100.0f); - + this->Tags.Add(FName("Enemy")); } @@ -49,6 +57,10 @@ void AEnemyCharacter::WeaponCooldownHandler() void AEnemyCharacter::BeginPlay() { Super::BeginPlay(); + + AEnemyAIController* controller = Cast(GetController()); + controller->GetBlackboardComponent()->SetValueAsFloat("CurrentHealth", GetHealthComponent()->GetCurrentHealth()); + GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged"); } void AEnemyCharacter::PlayOnFireAnimations() @@ -125,3 +137,12 @@ void AEnemyCharacter::ProcessHits(TArray hits) } } } + +void AEnemyCharacter::OnDamaged() +{ + Super::OnDamaged(); + + AEnemyAIController* controller = Cast(GetController()); + controller->GetBlackboardComponent()->SetValueAsFloat("CurrentHealth", GetHealthComponent()->GetCurrentHealth()); +} + diff --git a/Source/Nakatomi/EnemyCharacter.h b/Source/Nakatomi/EnemyCharacter.h index d998214..3e24291 100644 --- a/Source/Nakatomi/EnemyCharacter.h +++ b/Source/Nakatomi/EnemyCharacter.h @@ -4,6 +4,7 @@ #include "CoreMinimal.h" #include "NakatomiCharacter.h" +#include "PatrolRoute.h" #include "BehaviorTree/BehaviorTreeComponent.h" #include "RandomWeaponParameters.h" #include "EnemyCharacter.generated.h" @@ -17,6 +18,16 @@ class NAKATOMI_API AEnemyCharacter : public ANakatomiCharacter { GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, Meta = (AllowPrivateAccess = "true")) + APatrolRoute* CurrentPatrolRoute; + + UPROPERTY(EditAnywhere) + float AttackRadius = 300.0; + + UPROPERTY(EditAnywhere) + float DefendRadius = 500.0f; + private: UPROPERTY(EditDefaultsOnly, Meta = (AllowPrivateAccess = "true")) UBehaviorTree* BehaviourTree; @@ -44,4 +55,7 @@ private: virtual void CalculateHits(TArray* hits) override; virtual void ProcessHits(TArray hits) override; + +protected: + virtual void OnDamaged() override; }; diff --git a/Source/Nakatomi/EnemyHealthComponent.cpp b/Source/Nakatomi/EnemyHealthComponent.cpp new file mode 100644 index 0000000..820c831 --- /dev/null +++ b/Source/Nakatomi/EnemyHealthComponent.cpp @@ -0,0 +1,36 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "EnemyHealthComponent.h" + +#include "EnemyAIController.h" +#include "EnemyCharacter.h" + +void UEnemyHealthComponent::BeginPlay() +{ + Super::BeginPlay(); +} + +void UEnemyHealthComponent::TakeDamage(AActor* damagedActor, float damage, const UDamageType* damageType, + AController* instigatedBy, AActor* damageCauser) +{ + if (damagedActor == nullptr || IsDead || !CanDamage) + { + return; + } + + CurrentHealth -= damage; + + AEnemyCharacter* enemyCharacter = Cast(damagedActor); + UAISense_Damage::ReportDamageEvent(GetWorld(), damagedActor, damageCauser, 1, + damageCauser->GetTransform().GetLocation(), + damageCauser->GetTransform().GetLocation()); + + OnDamaged.ExecuteIfBound({damagedActor, damage, damageType, instigatedBy, damageCauser}); + + if (CurrentHealth <= 0.0f) + { + IsDead = true; + OnDeath.ExecuteIfBound({damagedActor, damage, damageType, instigatedBy, damageCauser}); + } +} diff --git a/Source/Nakatomi/EnemyHealthComponent.h b/Source/Nakatomi/EnemyHealthComponent.h new file mode 100644 index 0000000..fd7536c --- /dev/null +++ b/Source/Nakatomi/EnemyHealthComponent.h @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "HealthComponent.h" +#include "EnemyHealthComponent.generated.h" + +/** + * + */ +UCLASS() +class NAKATOMI_API UEnemyHealthComponent : public UHealthComponent +{ + GENERATED_BODY() + +protected: + virtual void BeginPlay() override; + + virtual void TakeDamage(AActor* damagedActor, float damage, const UDamageType* damageType, AController* instigatedBy, AActor* damageCauser) override; + +}; diff --git a/Source/Nakatomi/HealthComponent.h b/Source/Nakatomi/HealthComponent.h index 8e15ccd..9ec0b1d 100644 --- a/Source/Nakatomi/HealthComponent.h +++ b/Source/Nakatomi/HealthComponent.h @@ -39,7 +39,7 @@ public: FOnDamageDelegate OnDamaged; FOnDeathDelegate OnDeath; -private: +protected: UPROPERTY(EditDefaultsOnly) float MaxHealth = 100.f; @@ -55,7 +55,7 @@ public: UHealthComponent(); UFUNCTION() - void TakeDamage(AActor* damagedActor, float damage, const UDamageType* damageType, AController* instigatedBy, + virtual void TakeDamage(AActor* damagedActor, float damage, const UDamageType* damageType, AController* instigatedBy, AActor* damageCauser); UFUNCTION() diff --git a/Source/Nakatomi/NakatomiCMC.cpp b/Source/Nakatomi/NakatomiCMC.cpp index 1e45ce7..3898557 100644 --- a/Source/Nakatomi/NakatomiCMC.cpp +++ b/Source/Nakatomi/NakatomiCMC.cpp @@ -19,6 +19,12 @@ void UNakatomiCMC::InitializeComponent() NakatomiCharacterOwner = Cast(GetOwner()); } +void UNakatomiCMC::BeginPlay() +{ + Super::BeginPlay(); + DefaultMaxWalkSpeed = Walk_MaxWalkSpeed; +} + // Checks if we can combine the NewMove with the current move to save on data. // If all the data in a saved move is identical, if true, we cam tell the server to run the existing move instead. bool UNakatomiCMC::FSavedMove_Nakatomi::CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* InCharacter, @@ -271,6 +277,16 @@ bool UNakatomiCMC::IsCustomMovementMode(ECustomMovementMove InCustomMovementMode return MovementMode == MOVE_Custom && CustomMovementMode == InCustomMovementMode; } +void UNakatomiCMC::SetMaxWalkSpeed(float newMaxSpeed) +{ + Walk_MaxWalkSpeed = newMaxSpeed; +} + +void UNakatomiCMC::SetMaxWalkSpeedToDefault() +{ + Walk_MaxWalkSpeed = DefaultMaxWalkSpeed; +} + void UNakatomiCMC::EnterSlide() { Safe_bWantsToSlide = true; diff --git a/Source/Nakatomi/NakatomiCMC.h b/Source/Nakatomi/NakatomiCMC.h index 5ef4b35..6e422c2 100644 --- a/Source/Nakatomi/NakatomiCMC.h +++ b/Source/Nakatomi/NakatomiCMC.h @@ -108,6 +108,8 @@ class NAKATOMI_API UNakatomiCMC : public UCharacterMovementComponent UPROPERTY(Transient) ANakatomiCharacter* NakatomiCharacterOwner; + float DefaultMaxWalkSpeed; + public: UPROPERTY(BlueprintAssignable) FDashStartDelegate DashStartDelegate; @@ -118,6 +120,8 @@ public: protected: virtual void InitializeComponent() override; + virtual void BeginPlay() override; + virtual FNetworkPredictionData_Client* GetPredictionData_Client() const override; protected: @@ -167,6 +171,12 @@ public: UFUNCTION() bool IsCustomMovementMode(ECustomMovementMove InCustomMovementMode) const; + UFUNCTION() + void SetMaxWalkSpeed(float newMaxSpeed); + + UFUNCTION() + void SetMaxWalkSpeedToDefault(); + private: void EnterSlide(); void ExitSlide(); diff --git a/Source/Nakatomi/NakatomiCharacter.cpp b/Source/Nakatomi/NakatomiCharacter.cpp index ec54fda..536c469 100644 --- a/Source/Nakatomi/NakatomiCharacter.cpp +++ b/Source/Nakatomi/NakatomiCharacter.cpp @@ -14,9 +14,12 @@ ANakatomiCharacter::ANakatomiCharacter(const FObjectInitializer& ObjectInitializ NakatomiCMC = Cast(GetCharacterMovement()); - HealthComponent = CreateDefaultSubobject(TEXT("Health Component")); - HealthComponent->OnDamaged.BindUFunction(this, "OnDamaged"); - HealthComponent->OnDeath.BindUFunction(this, "OnDeath"); + // if (!HealthComponent) + // { + // HealthComponent = CreateDefaultSubobject(TEXT("Health Component")); + // HealthComponent->OnDamaged.BindUFunction(this, "OnDamaged"); + // HealthComponent->OnDeath.BindUFunction(this, "OnDeath"); + // } } // Called when the game starts or when spawned diff --git a/Source/Nakatomi/PatrolRoute.cpp b/Source/Nakatomi/PatrolRoute.cpp new file mode 100644 index 0000000..df7c94a --- /dev/null +++ b/Source/Nakatomi/PatrolRoute.cpp @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PatrolRoute.h" + +// Sets default values +APatrolRoute::APatrolRoute() +{ + PrimaryActorTick.bCanEverTick = false; + + Spline = CreateDefaultSubobject(TEXT("Spline")); + Spline->SetupAttachment(RootComponent); +} + +void APatrolRoute::IncrementPatrolRoute() +{ + if (PatrolIndex == Spline->GetNumberOfSplinePoints() - 1) + { + Direction = -1; + } + else if (PatrolIndex == 0) + { + Direction = 1; + } + + PatrolIndex += Direction; +} + +FVector APatrolRoute::GetSplinePointAtWorld() +{ + return GetSplinePointAtWorld(PatrolIndex); +} + +FVector APatrolRoute::GetSplinePointAtWorld(int pointIndex) +{ + return Spline->GetLocationAtSplinePoint(pointIndex, ESplineCoordinateSpace::World); +} diff --git a/Source/Nakatomi/PatrolRoute.h b/Source/Nakatomi/PatrolRoute.h new file mode 100644 index 0000000..ee9a9d2 --- /dev/null +++ b/Source/Nakatomi/PatrolRoute.h @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/SplineComponent.h" +#include "GameFramework/Actor.h" +#include "PatrolRoute.generated.h" + +UCLASS() +class NAKATOMI_API APatrolRoute : public AActor +{ + GENERATED_BODY() + +public: + + UPROPERTY(BlueprintReadWrite) + USplineComponent* Spline; + +private: + int PatrolIndex = 0; + + int Direction; + +public: + // Sets default values for this actor's properties + APatrolRoute(); + + void IncrementPatrolRoute(); + + FVector GetSplinePointAtWorld(); + + FVector GetSplinePointAtWorld(int pointIndex); +}; diff --git a/Source/Nakatomi/PlayerCharacter.cpp b/Source/Nakatomi/PlayerCharacter.cpp index de607e9..3846d19 100644 --- a/Source/Nakatomi/PlayerCharacter.cpp +++ b/Source/Nakatomi/PlayerCharacter.cpp @@ -30,6 +30,10 @@ APlayerCharacter::APlayerCharacter(const FObjectInitializer& ObjectInitializer) //bUseControllerRotationYaw = true; //bUseControllerRotationRoll = false; + SetHealthComponent(CreateDefaultSubobject(TEXT("Health Component"))); + GetHealthComponent()->OnDamaged.BindUFunction(this, "OnDamaged"); + GetHealthComponent()->OnDeath.BindUFunction(this, "OnDeath"); + // Setup the camera boom CameraSpringArmComponent = CreateDefaultSubobject(TEXT("CameraSpringArmComponent")); CameraSpringArmComponent->SetupAttachment(RootComponent); @@ -398,6 +402,7 @@ void APlayerCharacter::ProcessHits(TArray hits) { healthComponent->TakeDamage(Hit.GetActor(), CurrentWeapon->GetWeaponProperties()->WeaponDamage, nullptr, GetController(), this); + if (!healthComponent->GetIsDead()) { OnEnemyHit.ExecuteIfBound(); @@ -437,6 +442,8 @@ void APlayerCharacter::ProcessHits(TArray hits) true); } } + + MakeNoise(1, this, Hit.Location); } } @@ -639,6 +646,8 @@ void APlayerCharacter::OnFire() CurrentWeapon->PlayFireSoundAtLocation(this->GetTransform().GetLocation()); + MakeNoise(1,this, this->GetTransform().GetLocation()); + PlayOnFireAnimations(); CurrentWeapon->SetCurrentWeaponStatus(Cooldown); diff --git a/Source/Nakatomi/Tasks/BTTClearFocus.cpp b/Source/Nakatomi/Tasks/BTTClearFocus.cpp index 0cec164..16239b5 100644 --- a/Source/Nakatomi/Tasks/BTTClearFocus.cpp +++ b/Source/Nakatomi/Tasks/BTTClearFocus.cpp @@ -1,5 +1,13 @@ // Fill out your copyright notice in the Description page of Project Settings. -#include "Tasks/BTTClearFocus.h" +#include "../Tasks/BTTClearFocus.h" +#include "Nakatomi/EnemyAIController.h" + +EBTNodeResult::Type UBTTClearFocus::ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) +{ + auto enemyController = Cast(owner.GetAIOwner()); + enemyController->ClearFocus(EAIFocusPriority::Default); + return EBTNodeResult::Succeeded; +} diff --git a/Source/Nakatomi/Tasks/BTTClearFocus.h b/Source/Nakatomi/Tasks/BTTClearFocus.h index 7e7e552..513bf29 100644 --- a/Source/Nakatomi/Tasks/BTTClearFocus.h +++ b/Source/Nakatomi/Tasks/BTTClearFocus.h @@ -13,5 +13,8 @@ UCLASS() class NAKATOMI_API UBTTClearFocus : public UBTTaskNode { GENERATED_BODY() + +public: + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) override; }; diff --git a/Source/Nakatomi/Tasks/BTTMoveAlongPatrolRoute.cpp b/Source/Nakatomi/Tasks/BTTMoveAlongPatrolRoute.cpp new file mode 100644 index 0000000..aa8a0f3 --- /dev/null +++ b/Source/Nakatomi/Tasks/BTTMoveAlongPatrolRoute.cpp @@ -0,0 +1,28 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "../Tasks/BTTMoveAlongPatrolRoute.h" + +#include "navigationSystem.h" +#include "BehaviorTree/BlackboardComponent.h" +#include "Nakatomi/EnemyAIController.h" +#include "Nakatomi/NakatomiCMC.h" + +EBTNodeResult::Type UBTTMoveAlongPatrolRoute::ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) +{ + AEnemyAIController* enemyController = Cast(owner.GetAIOwner()); + AEnemyCharacter* enemyPawn = Cast(enemyController->GetPawn()); + + if (enemyPawn->CurrentPatrolRoute) + { + FVector location = enemyPawn->CurrentPatrolRoute->GetSplinePointAtWorld(); + UBlackboardComponent* blackboardComponent = owner.GetBlackboardComponent(); + blackboardComponent->SetValueAsVector(PatrolLocationKey.SelectedKeyName, location); + + enemyPawn->CurrentPatrolRoute->IncrementPatrolRoute(); + + return EBTNodeResult::Succeeded; + } + + return EBTNodeResult::Failed; +} diff --git a/Source/Nakatomi/Tasks/BTTMoveAlongPatrolRoute.h b/Source/Nakatomi/Tasks/BTTMoveAlongPatrolRoute.h new file mode 100644 index 0000000..71b4ad0 --- /dev/null +++ b/Source/Nakatomi/Tasks/BTTMoveAlongPatrolRoute.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "BTTMoveAlongPatrolRoute.generated.h" + +/** + * + */ +UCLASS() +class NAKATOMI_API UBTTMoveAlongPatrolRoute : public UBTTaskNode +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, Category = "Options", + Meta = (AllowPrivateAccess = "true", DisplayName = "Patrol Location Key")) + FBlackboardKeySelector PatrolLocationKey; + +public: + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) override; +}; diff --git a/Source/Nakatomi/Tasks/BTTSetMovementSpeed.cpp b/Source/Nakatomi/Tasks/BTTSetMovementSpeed.cpp new file mode 100644 index 0000000..eda9a35 --- /dev/null +++ b/Source/Nakatomi/Tasks/BTTSetMovementSpeed.cpp @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "../Tasks/BTTSetMovementSpeed.h" + +#include "Nakatomi/EnemyAIController.h" +#include "Nakatomi/NakatomiCMC.h" + +enum class EPatrolMovementEnum : uint8; + +EBTNodeResult::Type UBTTSetMovementSpeed::ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) +{ + AEnemyAIController* enemyController = Cast(owner.GetAIOwner()); + AEnemyCharacter* enemyPawn = Cast(enemyController->GetPawn()); + + switch (MaxWalkSpeedKey) + { + case EPatrolMovementEnum::SLOWWALK: + enemyPawn->GetCharacterMovementComponent()->SetMaxWalkSpeed(slowWalkSpeed); + break; + case EPatrolMovementEnum::WALK: + enemyPawn->GetCharacterMovementComponent()->SetMaxWalkSpeed(walkSpeed); + break; + case EPatrolMovementEnum::SPRINT: + enemyPawn->GetCharacterMovementComponent()->SetMaxWalkSpeed(sprintSpeed); + break; + default: + enemyPawn->GetCharacterMovementComponent()->SetMaxWalkSpeedToDefault(); + break; + } + + return EBTNodeResult::Succeeded; +} diff --git a/Source/Nakatomi/Tasks/BTTSetMovementSpeed.h b/Source/Nakatomi/Tasks/BTTSetMovementSpeed.h new file mode 100644 index 0000000..4a90608 --- /dev/null +++ b/Source/Nakatomi/Tasks/BTTSetMovementSpeed.h @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "Nakatomi/EPatrolMovementEnum.h" +#include "BTTSetMovementSpeed.generated.h" + +/** + * + */ +UCLASS() +class NAKATOMI_API UBTTSetMovementSpeed : public UBTTaskNode +{ + GENERATED_BODY() + +public: + + UPROPERTY(EditAnywhere, Category = "Options", + Meta = (AllowPrivateAccess = "true", DisplayName = "Max Walk Speed Key")) + EPatrolMovementEnum MaxWalkSpeedKey; + +private: + float slowWalkSpeed = 250.0f; + + float walkSpeed = 500.0f; + + float sprintSpeed = 750.0f; + +public: + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) override; + +}; diff --git a/Source/Nakatomi/Tasks/BTTSetState.cpp b/Source/Nakatomi/Tasks/BTTSetState.cpp new file mode 100644 index 0000000..afb0f28 --- /dev/null +++ b/Source/Nakatomi/Tasks/BTTSetState.cpp @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "../Tasks/BTTSetState.h" + +#include "Nakatomi/EnemyAIController.h" + +EBTNodeResult::Type UBTTSetState::ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) +{ + if (AEnemyAIController* EnemyController = Cast(owner.GetAIOwner())) + { + EnemyController->SetState(NewState); + return EBTNodeResult::Succeeded; + } + + return EBTNodeResult::Failed; +} diff --git a/Source/Nakatomi/Tasks/BTTSetState.h b/Source/Nakatomi/Tasks/BTTSetState.h new file mode 100644 index 0000000..2aa3518 --- /dev/null +++ b/Source/Nakatomi/Tasks/BTTSetState.h @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BTTaskNode.h" +#include "Nakatomi/EAIState.h" +#include "BTTSetState.generated.h" + +/** + * + */ +UCLASS() +class NAKATOMI_API UBTTSetState : public UBTTaskNode +{ + GENERATED_BODY() + +public: + + UPROPERTY(EditAnywhere, Category = "Options", + Meta = (AllowPrivateAccess = "true", DisplayName = "New State")) + EAIState NewState; + +public: + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& owner, uint8* memory) override; + +};