diff --git a/COMP250_1_2101327_AI/Content/Main.umap b/COMP250_1_2101327_AI/Content/Main.umap index b2c7b41..25efbee 100644 --- a/COMP250_1_2101327_AI/Content/Main.umap +++ b/COMP250_1_2101327_AI/Content/Main.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9afc72fdb57e571cd6825ba08df57e5d348f4d0c637a1dc9e749b73856d25832 -size 40282 +oid sha256:4dabd96b91e537f957841dd9c905d313433780c6ffa20dcbad3898e6f45e6b2c +size 40330 diff --git a/COMP250_1_2101327_AI/Content/StarterContent/Audio/Collapse01.uasset b/COMP250_1_2101327_AI/Content/StarterContent/Audio/Collapse01.uasset index 7f0ee46..10eb1d7 100644 --- a/COMP250_1_2101327_AI/Content/StarterContent/Audio/Collapse01.uasset +++ b/COMP250_1_2101327_AI/Content/StarterContent/Audio/Collapse01.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5565f16f5c4074ccbc5c0f305a5a21edbe258c6246cc40fd8e9f39ff7906a70b +oid sha256:054f961ce7befe9c615be25a82ecadf95916f6b86afcb3057979e48be7bc38f5 size 353935 diff --git a/COMP250_1_2101327_AI/Source/COMP250_1_2101327_AI/GOAP/GOAPAgent.cpp b/COMP250_1_2101327_AI/Source/COMP250_1_2101327_AI/GOAP/GOAPAgent.cpp index 9a8e43b..0666c12 100644 --- a/COMP250_1_2101327_AI/Source/COMP250_1_2101327_AI/GOAP/GOAPAgent.cpp +++ b/COMP250_1_2101327_AI/Source/COMP250_1_2101327_AI/GOAP/GOAPAgent.cpp @@ -4,7 +4,6 @@ #include "GOAPAgent.h" #include "Actions/Combo_P.h" -#include "Actions/DefaultAttack.h" // Sets default values for this component's properties @@ -23,30 +22,21 @@ void UGOAPAgent::BeginPlay() { Super::BeginPlay(); - CombatSystem = Cast(GetWorld()->GetGameState()); + //Gets all classes that inherit from UGOAPAction and adds them to the AvailableActions array + TArray ActionClasses; + GetDerivedClasses(UGOAPAction::StaticClass(), ActionClasses, false); + for (UClass* ActionClass : ActionClasses) + { + UGOAPAction* Action = NewObject(GetWorld(), ActionClass); + Action->Init(); + AvailableActions.Add(Action); + } - UGOAPAction* DefaultAttack = NewObject(GetWorld(), UDefaultAttack::StaticClass()); - DefaultAttack->Init(); - AvailableActions.Add(DefaultAttack); - UGOAPAction* Combo_P = NewObject(GetWorld(), UCombo_P::StaticClass()); - Combo_P->Init(); - AvailableActions.Add(Combo_P); + //Sort AvailableActions by cost + AvailableActions.Sort([](const UGOAPAction& A, const UGOAPAction& B) { return A.ActionCost < B.ActionCost; }); } - -TMap UGOAPAgent::GetWorldState() -{ - TMap WorldState; - WorldState.Add("PlayerHealth", *CombatSystem->PlayerHealth); - WorldState.Add("EnemyHealth", *CombatSystem->EnemyHealth); - WorldState.Add("ProbertiumResource", CombatSystem->EnemyProbertiumResource); - WorldState.Add("EisResource", CombatSystem->EnemyEisResource); - WorldState.Add("AzosResource", CombatSystem->EnemyAzosResource); - WorldState.Add("IroquoidResource", CombatSystem->EnemyIroquoidResource); - return WorldState; -} - -bool UGOAPAgent::BuildActionGraph(UActionNode* Parent, TArray& SuccessfulLeaves, TMap WorldState, TMap AgentGoals) +bool UGOAPAgent::BuildActionGraph(UActionNode* Parent, TArray& SuccessfulLeaves, UWorldState* WorldState, TMap AgentGoals) { bool bFoundAPlan = false; @@ -54,17 +44,18 @@ bool UGOAPAgent::BuildActionGraph(UActionNode* Parent, TArray& Suc { if (Action->CheckPreConditions(WorldState)) { - TMap NewWorldState = Action->ApplyEffects(WorldState); + UWorldState* NewWorldState = Action->ApplyEffects(WorldState); UActionNode* NewNode = NewObject(); NewNode->Init(Parent, Action, NewWorldState, Parent->Cost + Action->ActionCost); - if (NewWorldState["PlayerHealth"] <= 0) + if (NewWorldState->State["PlayerHealth"] <= 0) { SuccessfulLeaves.Add(NewNode); bFoundAPlan = true; } - else + else if (!SeenStates.Contains(NewWorldState) && !bFoundAPlan) { + SeenStates.Add(NewWorldState); TArray NewLeaves; if (BuildActionGraph(NewNode, NewLeaves, NewWorldState, AgentGoals)) { @@ -75,6 +66,17 @@ bool UGOAPAgent::BuildActionGraph(UActionNode* Parent, TArray& Suc } } + //Log the plan + if (bFoundAPlan) + { + UE_LOG(LogTemp, Warning, TEXT("Found a plan!")); + // UActionNode* CurrentNode = SuccessfulLeaves[0]; + // while (CurrentNode->Parent != nullptr) + // { + // UE_LOG(LogTemp, Warning, TEXT("%s"), *CurrentNode->Action->GetName()); + // CurrentNode = CurrentNode->Parent; + // } + } return bFoundAPlan; } @@ -86,13 +88,16 @@ void UGOAPAgent::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompo // ... } -TArray UGOAPAgent::Plan(TMap WorldState, TMap AgentGoals) +TArray UGOAPAgent::Plan(UWorldState* WorldState, TMap AgentGoals) { TArray ActionPlan; UActionNode* RootActionNode = NewObject(); RootActionNode->Init(nullptr, nullptr, WorldState, 0); TArray SuccessfulLeaves; + SeenStates.Empty(); + SeenStates.Add(WorldState); + if (BuildActionGraph(RootActionNode, SuccessfulLeaves, WorldState, AgentGoals)) { //Find the cheapest leaf @@ -123,5 +128,7 @@ TArray UGOAPAgent::Plan(TMap WorldState, TMap State; + UWorldState* State; float Cost; - void Init(UActionNode* ParentNode, UGOAPAction* GOAPAction, TMap ProceduralState, float TotalCost) + void Init(UActionNode* ParentNode, UGOAPAction* GOAPAction, UWorldState* ProceduralState, float TotalCost) { Parent = ParentNode; Action = GOAPAction; @@ -50,19 +51,14 @@ protected: // Called when the game starts virtual void BeginPlay() override; - UPROPERTY() - ATurnBaseCombatV2* CombatSystem; - UFUNCTION() - bool BuildActionGraph(UActionNode* Parent, TArray& SuccessfulLeaves, TMap WorldState, TMap AgentGoals); + bool BuildActionGraph(UActionNode* Parent, TArray& SuccessfulLeaves, UWorldState* WorldState, TMap AgentGoals); + TSet SeenStates; public: // Called every frame virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; UFUNCTION() - TArray Plan(TMap WorldState, TMap AgentGoals); - - UFUNCTION() - TMap GetWorldState(); + TArray Plan(UWorldState* WorldState, TMap AgentGoals); };