diff --git a/EndlessVendetta/.idea/.idea.EndlessVendetta.dir/.idea/indexLayout.xml b/EndlessVendetta/.idea/.idea.EndlessVendetta.dir/.idea/indexLayout.xml index 5c30a127..7b08163c 100644 --- a/EndlessVendetta/.idea/.idea.EndlessVendetta.dir/.idea/indexLayout.xml +++ b/EndlessVendetta/.idea/.idea.EndlessVendetta.dir/.idea/indexLayout.xml @@ -1,9 +1,7 @@ - - ../../Endless-Vendetta - + diff --git a/EndlessVendetta/.idea/.idea.EndlessVendetta.dir/.idea/vcs.xml b/EndlessVendetta/.idea/.idea.EndlessVendetta.dir/.idea/vcs.xml deleted file mode 100644 index 6c0b8635..00000000 --- a/EndlessVendetta/.idea/.idea.EndlessVendetta.dir/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/EndlessVendetta/Content/AI/Companion/Generic/CompanionCharacter.uasset b/EndlessVendetta/Content/AI/Companion/Generic/CompanionCharacter.uasset index 1d6453bf..756cb54f 100644 --- a/EndlessVendetta/Content/AI/Companion/Generic/CompanionCharacter.uasset +++ b/EndlessVendetta/Content/AI/Companion/Generic/CompanionCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e98da72016a1ef89567571563bb8ddcb251370a7ae7f39b5a0ef17741de9154d -size 32421 +oid sha256:81819e2798f36f0fba8aa19cc63f66025941404eef5b0bab1cce20b9fc9bc63e +size 33153 diff --git a/EndlessVendetta/Content/AI/Enemy/Basic/BB_BasicEnemy.uasset b/EndlessVendetta/Content/AI/Enemy/Basic/BB_BasicEnemy.uasset index 56819b9d..10435623 100644 --- a/EndlessVendetta/Content/AI/Enemy/Basic/BB_BasicEnemy.uasset +++ b/EndlessVendetta/Content/AI/Enemy/Basic/BB_BasicEnemy.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d175544d93e03c9c35e6fa9e17caa58f91fa9c2227be1f62ddc9234b095e8d46 -size 4420 +oid sha256:d0a3db5cfec43d17f9da7040dd28af3f31ff5cb2d00756125f57bda2281fb3b6 +size 5092 diff --git a/EndlessVendetta/Content/AI/Enemy/Basic/BP_BasicEnemyCharacter.uasset b/EndlessVendetta/Content/AI/Enemy/Basic/BP_BasicEnemyCharacter.uasset index 894c9059..dfd8779e 100644 --- a/EndlessVendetta/Content/AI/Enemy/Basic/BP_BasicEnemyCharacter.uasset +++ b/EndlessVendetta/Content/AI/Enemy/Basic/BP_BasicEnemyCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0cce34a40f6aed425749f0c271aa6ba31b8bfea2ffafb3446559e374f0676b4b -size 32990 +oid sha256:d3303248d6f8042f7821695c75f275128c8198ff1229097ad439b09fb12d423d +size 33443 diff --git a/EndlessVendetta/Content/AI/Enemy/Basic/BP_PatrolPath.uasset b/EndlessVendetta/Content/AI/Enemy/Basic/BP_PatrolPath.uasset new file mode 100644 index 00000000..6f508524 --- /dev/null +++ b/EndlessVendetta/Content/AI/Enemy/Basic/BP_PatrolPath.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:29562c22635b352e858f43519d92020839358b09afd4a5138f4eba660bd10143 +size 23184 diff --git a/EndlessVendetta/Content/AI/Enemy/Basic/BT_BasicEnemy.uasset b/EndlessVendetta/Content/AI/Enemy/Basic/BT_BasicEnemy.uasset index 63d6a5f9..c09bdac3 100644 --- a/EndlessVendetta/Content/AI/Enemy/Basic/BT_BasicEnemy.uasset +++ b/EndlessVendetta/Content/AI/Enemy/Basic/BT_BasicEnemy.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7edfafa0555092e33fe013a8130878ffa4cc97c34d1cd617bc71bb03bd5d194c -size 19535 +oid sha256:b3a4bb63ecee2b90ddaf61c85f3d7bc03086141eac00a6c366858a827f5c16fe +size 24774 diff --git a/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/6/3L/ZL9NLFPHO4RXCMXRLPZ3ST.uasset b/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/6/3L/ZL9NLFPHO4RXCMXRLPZ3ST.uasset new file mode 100644 index 00000000..a0e4b6ce --- /dev/null +++ b/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/6/3L/ZL9NLFPHO4RXCMXRLPZ3ST.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:54b0926e4be9c9b5f0c3b7857ac67678a44681551b4769b33fe7ec6e4c535261 +size 3787 diff --git a/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/A/UU/P4XZ4FDZKD5IXIWK3JDDDK.uasset b/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/A/UU/P4XZ4FDZKD5IXIWK3JDDDK.uasset index c31f9729..b279c76a 100644 --- a/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/A/UU/P4XZ4FDZKD5IXIWK3JDDDK.uasset +++ b/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/A/UU/P4XZ4FDZKD5IXIWK3JDDDK.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cf054aae033d323e2dc383293f32913ba2abc9f97ae89368159c2b9eb8c7e8bd -size 5073 +oid sha256:0825e2d72278674564a97acf017751f5d2ae310ad8c3a0786060fe2c538f37bd +size 5597 diff --git a/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/B/AZ/GX8EY01G00J28SE17R0FJV.uasset b/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/B/AZ/GX8EY01G00J28SE17R0FJV.uasset index b1ec8842..b60728b0 100644 --- a/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/B/AZ/GX8EY01G00J28SE17R0FJV.uasset +++ b/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/B/AZ/GX8EY01G00J28SE17R0FJV.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b846a25931a6e0277f004c0f41c52eb17b7ea951697783592186c6cb01904bfc -size 5216 +oid sha256:21099d36885bd35d8fc3ced5641695e285425bc2a8bd916912c9a35daa30b5a9 +size 6064 diff --git a/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/E/PJ/BY6E8JXZSRNMAW3DFHRHRJ.uasset b/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/E/PJ/BY6E8JXZSRNMAW3DFHRHRJ.uasset deleted file mode 100644 index 4abdf431..00000000 --- a/EndlessVendetta/Content/__ExternalActors__/Levels/EnemyAITest/E/PJ/BY6E8JXZSRNMAW3DFHRHRJ.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cfb0f1718ab71a979c83b7884652cb8b9a757abf7c2e17c1d3b356f1ef4228f7 -size 5313 diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.cpp index e6b4e22d..9135da93 100644 --- a/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.cpp +++ b/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.cpp @@ -80,6 +80,11 @@ float AAICharacter::TakeDamage(const float DamageAmount, FDamageEvent const& Dam return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser); } +APatrolPath* AAICharacter::GetPatrolPath() const +{ + return PatrolPath; +} + void AAICharacter::SetupStimuliSourceComponent() { StimuliSourceComponent = CreateDefaultSubobject(TEXT("Stimuli Source Component")); diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.h b/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.h index 9431cbce..44bbd309 100644 --- a/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.h +++ b/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.h @@ -3,6 +3,7 @@ #pragma once #include "CoreMinimal.h" +#include "PatrolPath.h" #include "BehaviorTree/BehaviorTree.h" #include "GameFramework/Character.h" #include "AICharacter.generated.h" @@ -30,9 +31,6 @@ protected: // Called when the game starts or when spawned virtual void BeginPlay() override; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI") - UBehaviorTree* BehaviorTree; - UPROPERTY() class UAIPerceptionStimuliSourceComponent* StimuliSourceComponent; void SetupStimuliSourceComponent(); @@ -49,4 +47,14 @@ public: UFUNCTION(BlueprintCallable, Category = "Damage Control") virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override; + + UFUNCTION() + APatrolPath* GetPatrolPath() const; + +private: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI", meta = (AllowPrivateAccess = "true")) + UBehaviorTree* BehaviorTree; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI", meta = (AllowPrivateAccess = "true")) + APatrolPath* PatrolPath; }; diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/PatrolPath.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/PatrolPath.cpp new file mode 100644 index 00000000..18c7f07a --- /dev/null +++ b/EndlessVendetta/Source/EndlessVendetta/AI/PatrolPath.cpp @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "PatrolPath.h" + + +// Sets default values +APatrolPath::APatrolPath() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = false; +} + +FVector APatrolPath::GetPatrolPoint(int const Index) const +{ + return PatrolPoint[Index]; +} + +int APatrolPath::Num() const +{ + return PatrolPoint.Num(); +} diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/PatrolPath.h b/EndlessVendetta/Source/EndlessVendetta/AI/PatrolPath.h new file mode 100644 index 00000000..f9236526 --- /dev/null +++ b/EndlessVendetta/Source/EndlessVendetta/AI/PatrolPath.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "PatrolPath.generated.h" + +UCLASS() +class ENDLESSVENDETTA_API APatrolPath : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + APatrolPath(); + + FVector GetPatrolPoint(int const Index) const; + int Num() const; + +private: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI", meta = (MakeEditWidget = "true", AllowPrivateAccess = "true")) + TArray PatrolPoint; +}; diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/BTTask_AttackPlayer.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_AttackPlayer.cpp similarity index 94% rename from EndlessVendetta/Source/EndlessVendetta/AI/BTTask_AttackPlayer.cpp rename to EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_AttackPlayer.cpp index 74b01095..ce49ec2d 100644 --- a/EndlessVendetta/Source/EndlessVendetta/AI/BTTask_AttackPlayer.cpp +++ b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_AttackPlayer.cpp @@ -3,7 +3,7 @@ #include "BTTask_AttackPlayer.h" -#include "AI_EnemyController.h" +#include "EndlessVendetta/AI/AI_EnemyController.h" #include "BehaviorTree/BlackboardComponent.h" UBTTask_AttackPlayer::UBTTask_AttackPlayer(FObjectInitializer const& ObjectInitializer) diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/BTTask_AttackPlayer.h b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_AttackPlayer.h similarity index 100% rename from EndlessVendetta/Source/EndlessVendetta/AI/BTTask_AttackPlayer.h rename to EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_AttackPlayer.h diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindCover.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindCover.cpp similarity index 100% rename from EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindCover.cpp rename to EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindCover.cpp diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindCover.h b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindCover.h similarity index 100% rename from EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindCover.h rename to EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindCover.h diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindPathPoint.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindPathPoint.cpp new file mode 100644 index 00000000..1643c153 --- /dev/null +++ b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindPathPoint.cpp @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_FindPathPoint.h" + +#include "BehaviorTree/BlackboardComponent.h" +#include "EndlessVendetta/AI/AI_EnemyController.h" +#include "EndlessVendetta/AI/EnemyCharacter.h" + +UBTTask_FindPathPoint::UBTTask_FindPathPoint(FObjectInitializer const& ObjectInitializer) +{ + NodeName = TEXT("Find Path Point"); +} + +EBTNodeResult::Type UBTTask_FindPathPoint::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + if (const AAI_EnemyController* const AIEnemyController = Cast(OwnerComp.GetAIOwner())) + { + if (UBlackboardComponent* const BlackboardComponent = OwnerComp.GetBlackboardComponent()) + { + int const Index = BlackboardComponent->GetValueAsInt(GetSelectedBlackboardKey()); + if (const AEnemyCharacter* const EnemyCharacter = Cast(AIEnemyController->GetPawn())) + { + FVector const RelativePatrolPoint = EnemyCharacter->GetPatrolPath()->GetPatrolPoint(Index); + FVector const GlobalPointLocation = EnemyCharacter->GetPatrolPath()->GetActorTransform().TransformPosition(RelativePatrolPoint); + BlackboardComponent->SetValueAsVector(PatrolPathVectorKey.SelectedKeyName, GlobalPointLocation); + + FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); + return EBTNodeResult::Succeeded; + } + } + } + return EBTNodeResult::Failed; +} diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindPathPoint.h b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindPathPoint.h new file mode 100644 index 00000000..e329006a --- /dev/null +++ b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindPathPoint.h @@ -0,0 +1,24 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h" +#include "BTTask_FindPathPoint.generated.h" + +/** + * + */ +UCLASS() +class ENDLESSVENDETTA_API UBTTask_FindPathPoint : public UBTTask_BlackboardBase +{ + GENERATED_BODY() + +public: + explicit UBTTask_FindPathPoint(FObjectInitializer const& ObjectInitializer); + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + +private: + UPROPERTY(EditAnywhere, Category = "Blackboard", meta=(AllowPrivateAccess = "true")) + FBlackboardKeySelector PatrolPathVectorKey; +}; diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindPlayerLocation.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindPlayerLocation.cpp similarity index 100% rename from EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindPlayerLocation.cpp rename to EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindPlayerLocation.cpp diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindPlayerLocation.h b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindPlayerLocation.h similarity index 100% rename from EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindPlayerLocation.h rename to EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindPlayerLocation.h diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindRandomLocation.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindRandomLocation.cpp similarity index 95% rename from EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindRandomLocation.cpp rename to EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindRandomLocation.cpp index 62a3d9b8..af11c428 100644 --- a/EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindRandomLocation.cpp +++ b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindRandomLocation.cpp @@ -3,7 +3,7 @@ #include "BTTask_FindRandomLocation.h" -#include "AI_EnemyController.h" +#include "EndlessVendetta/AI/AI_EnemyController.h" #include "NavigationSystem.h" #include "BehaviorTree/BlackboardComponent.h" diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindRandomLocation.h b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindRandomLocation.h similarity index 100% rename from EndlessVendetta/Source/EndlessVendetta/AI/BTTask_FindRandomLocation.h rename to EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_FindRandomLocation.h diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_IncrementPathIndex.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_IncrementPathIndex.cpp new file mode 100644 index 00000000..cfc7b788 --- /dev/null +++ b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_IncrementPathIndex.cpp @@ -0,0 +1,47 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "BTTask_IncrementPathIndex.h" + +#include "BehaviorTree/BlackboardComponent.h" +#include "EndlessVendetta/AI/AI_EnemyController.h" +#include "EndlessVendetta/AI/EnemyCharacter.h" + +UBTTask_IncrementPathIndex::UBTTask_IncrementPathIndex(FObjectInitializer const& ObjectInitializer) +{ + NodeName = TEXT("Increment Path Index"); +} + +EBTNodeResult::Type UBTTask_IncrementPathIndex::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) +{ + if (AAI_EnemyController* const EnemyController = Cast(OwnerComp.GetOwner())) + { + if (AEnemyCharacter* const EnemyCharacter = Cast(EnemyController->GetPawn())) + { + if (UBlackboardComponent* const BlackboardComponent = OwnerComp.GetBlackboardComponent()) + { + int const NumberOfPoints = EnemyCharacter->GetPatrolPath()->Num(); + int const MinIndex = 0; + int const MaxIndex = NumberOfPoints - 1; + int CurrentIndex = BlackboardComponent->GetValueAsInt(GetSelectedBlackboardKey()); + + if (bBiDirectional) + { + if (CurrentIndex >= MaxIndex && DirectionType == Forward) + { + DirectionType = Backward; + } + else if (CurrentIndex == MinIndex && DirectionType == Backward) + { + DirectionType = Forward; + } + } + BlackboardComponent->SetValueAsInt(GetSelectedBlackboardKey(), (DirectionType == Forward ? ++CurrentIndex : --CurrentIndex) % NumberOfPoints); + + FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); + return EBTNodeResult::Succeeded; + } + } + } + return EBTNodeResult::Failed; +} diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_IncrementPathIndex.h b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_IncrementPathIndex.h new file mode 100644 index 00000000..0f9c3442 --- /dev/null +++ b/EndlessVendetta/Source/EndlessVendetta/AI/Tasks/BTTask_IncrementPathIndex.h @@ -0,0 +1,32 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/Tasks/BTTask_BlackboardBase.h" +#include "BTTask_IncrementPathIndex.generated.h" + +/** + * + */ +UCLASS() +class ENDLESSVENDETTA_API UBTTask_IncrementPathIndex : public UBTTask_BlackboardBase +{ + GENERATED_BODY() + +public: + explicit UBTTask_IncrementPathIndex(FObjectInitializer const& ObjectInitializer); + virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; + +private: + enum EPathFollowType + { + Forward, + Backward + }; + + EPathFollowType DirectionType = Forward; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI", meta = (AllowPrivateAccess = "true")) + bool bBiDirectional = false; +};