Hi,
I am trying to create an environment query from c++ code at load time, so it can be modified at runtime and so I can use a context that just pulls values from a static array of targetable entities.
I am deriving an example query from the eqs quickstart tutorial in the official docs. The source code of the environment query system seems to indicate a way to port the query to c++, what I have is this:
static void FindCoverAttackSpot(FString name, float minDist, float maxDist, float optimalDist) {
UEnvQuery* eq = NewObject<UEnvQuery>();
TArray<UEnvQueryOption*>& options=eq->GetOptionsMutable();
options.Reset();
options.Add(NewObject<UEnvQueryOption>());
options[0]->Generator = NewObject<UEnvQueryGenerator_ActorsOfClass>();
Cast<UEnvQueryGenerator_ActorsOfClass>(options[0]->Generator)->SearchRadius.DefaultValue = 10.0;
Cast<UEnvQueryGenerator_ActorsOfClass>(options[0]->Generator)->SearchedActorClass = ACoverAttackSpot::StaticClass();
options[0]->Tests.Add(NewObject<UEnvQueryTest_Distance>());
Cast<UEnvQueryTest_Distance>(options[0]->Tests[0])->TestMode = EEnvTestDistance::Distance3D;
Cast<UEnvQueryTest_Distance>(options[0]->Tests[0])->DistanceTo = UPlayersContext::StaticClass();
Cast<UEnvQueryTest_Distance>(options[0]->Tests[0])->FloatValueMin.DefaultValue = minDist;
Cast<UEnvQueryTest_Distance>(options[0]->Tests[0])->FloatValueMax.DefaultValue = maxDist;
Cast<UEnvQueryTest_Distance>(options[0]->Tests[0])->ReferenceValue.DefaultValue = optimalDist;
Cast<UEnvQueryTest_Distance>(options[0]->Tests[0])->FilterType = EEnvTestFilterType::Range;
options[0]->Tests.Add(NewObject<UEnvQueryTest_Distance>());
Cast<UEnvQueryTest_Distance>(options[0]->Tests[1])->TestMode = EEnvTestDistance::Distance3D;
Cast<UEnvQueryTest_Distance>(options[0]->Tests[1])->DistanceTo = UEnvQueryContext_Querier::StaticClass();
Cast<UEnvQueryTest_Distance>(options[0]->Tests[1])->FloatValueMin.DefaultValue = 0.0;
Cast<UEnvQueryTest_Distance>(options[0]->Tests[1])->FloatValueMax.DefaultValue = 10000.0;
Cast<UEnvQueryTest_Distance>(options[0]->Tests[1])->ReferenceValue.DefaultValue = 1.0;
Cast<UEnvQueryTest_Distance>(options[0]->Tests[1])->FilterType = EEnvTestFilterType::Range;
options[0]->Tests.Add(NewObject<UEnvQueryTest_Trace>());
Cast<UEnvQueryTest_Trace>(options[0]->Tests[2])->Context = UPlayersContext::StaticClass();
Cast<UEnvQueryTest_Trace>(options[0]->Tests[2])->FilterType = EEnvTestFilterType::Match;
Cast<UEnvQueryTest_Trace>(options[0]->Tests[2])->BoolValue.DefaultValue=false;
options[0]->Tests.Add(NewObject<UEnvQueryTest_Dot_Exposed>());
Cast<UEnvQueryTest_Dot_Exposed>(options[0]->Tests[3])->SetDefaults();
options[0]->Tests.Add(NewObject<UEnvQueryTest_Pathfinding>());
Cast<UEnvQueryTest_Pathfinding>(options[0]->Tests[4])->TestMode = EEnvTestPathfinding::PathCost;
Cast<UEnvQueryTest_Pathfinding>(options[0]->Tests[4])->Context = UEnvQueryContext_Querier::StaticClass();
Cast<UEnvQueryTest_Pathfinding>(options[0]->Tests[4])->PathFromContext.DefaultValue = true;
Cast<UEnvQueryTest_Pathfinding>(options[0]->Tests[4])->SkipUnreachable.DefaultValue = true;
queries.Add(name, eq);
}
This differs from the tutorial in some of the parameters and logic, but hopefully you can see what I am trying to do.
UPlayersContext has the following method:
void UPlayersContext::ProvideContext(FEnvQueryInstance& QueryInstance, FEnvQueryContextData& ContextData) const {
AActor* QuerierActor = Cast<AActor>(QueryInstance.Owner.Get());
UBlackboardComponent* BB = QuerierActor->FindComponentByClass<UBlackboardComponent>();
if (BB != nullptr) {
AActor* target = Cast<AActor>(BB->GetValue<UBlackboardKeyType_Object>(FName(TEXT("Target"))));
if (target != nullptr) {
UEnvQueryItemType_Actor::SetContextHelper(ContextData, target);
}
}
TArray<AActor*> ResultingActorsSet;
std::vector<AActor*> res1 = CharacterRegistry::GetPlayers();
for (int i = 0, e = res1.size(); i < e; ++i) {
ResultingActorsSet.Add(res1[i]);
}
UEnvQueryItemType_Actor::SetContextHelper(ContextData, ResultingActorsSet);
}
Problem is, I get some link errors:
2>BehaviorRegistry.cpp.obj : error LNK2019: unresolved external symbol "private: static class UClass * __cdecl UEnvQueryGenerator_ActorsOfClass::GetPrivateStaticClass(wchar_t const *)" (?GetPrivateStaticClass@UEnvQueryGenerator_ActorsOfClass@@CAPEAVUClass@@PEB_W@Z) referenced in function "class UEnvQueryGenerator_ActorsOfClass * __cdecl Cast<class UEnvQueryGenerator_ActorsOfClass,class UEnvQueryGenerator>(class UEnvQueryGenerator *)" (??$Cast@VUEnvQueryGenerator_ActorsOfClass@@VUEnvQueryGenerator@@@@YAPEAVUEnvQueryGenerator_ActorsOfClass@@PEAVUEnvQueryGenerator@@@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "private: static class UClass * __cdecl UEnvQueryGenerator_ActorsOfClass::GetPrivateStaticClass(wchar_t const *)" (?GetPrivateStaticClass@UEnvQueryGenerator_ActorsOfClass@@CAPEAVUClass@@PEB_W@Z)
2>BehaviorRegistry.cpp.obj : error LNK2019: unresolved external symbol "public: __cdecl UEnvQueryGenerator_ActorsOfClass::UEnvQueryGenerator_ActorsOfClass(class FObjectInitializer const &)" (??0UEnvQueryGenerator_ActorsOfClass@@QEAA@AEBVFObjectInitializer@@@Z) referenced in function "public: static void __cdecl BehaviorRegistry::FindCoverAttackSpot(class FString,float,float,float)" (?FindCoverAttackSpot@BehaviorRegistry@@SAXVFString@@MMM@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "public: __cdecl UEnvQueryGenerator_ActorsOfClass::UEnvQueryGenerator_ActorsOfClass(class FObjectInitializer const &)" (??0UEnvQueryGenerator_ActorsOfClass@@QEAA@AEBVFObjectInitializer@@@Z)
2>BehaviorRegistry.cpp.obj : error LNK2019: unresolved external symbol "private: static class UClass * __cdecl UEnvQueryTest_Pathfinding::GetPrivateStaticClass(wchar_t const *)" (?GetPrivateStaticClass@UEnvQueryTest_Pathfinding@@CAPEAVUClass@@PEB_W@Z) referenced in function "class UEnvQueryTest_Pathfinding * __cdecl Cast<class UEnvQueryTest_Pathfinding,class UEnvQueryTest>(class UEnvQueryTest *)" (??$Cast@VUEnvQueryTest_Pathfinding@@VUEnvQueryTest@@@@YAPEAVUEnvQueryTest_Pathfinding@@PEAVUEnvQueryTest@@@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "private: static class UClass * __cdecl UEnvQueryTest_Pathfinding::GetPrivateStaticClass(wchar_t const *)" (?GetPrivateStaticClass@UEnvQueryTest_Pathfinding@@CAPEAVUClass@@PEB_W@Z)
2>BehaviorRegistry.cpp.obj : error LNK2019: unresolved external symbol "public: __cdecl UEnvQueryTest_Pathfinding::UEnvQueryTest_Pathfinding(class FObjectInitializer const &)" (??0UEnvQueryTest_Pathfinding@@QEAA@AEBVFObjectInitializer@@@Z) referenced in function "public: static void __cdecl BehaviorRegistry::FindCoverAttackSpot(class FString,float,float,float)" (?FindCoverAttackSpot@BehaviorRegistry@@SAXVFString@@MMM@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "public: __cdecl UEnvQueryTest_Pathfinding::UEnvQueryTest_Pathfinding(class FObjectInitializer const &)" (??0UEnvQueryTest_Pathfinding@@QEAA@AEBVFObjectInitializer@@@Z)
2>BehaviorRegistry.cpp.obj : error LNK2019: unresolved external symbol "private: static class UClass * __cdecl UEnvQueryTest_Distance::GetPrivateStaticClass(wchar_t const *)" (?GetPrivateStaticClass@UEnvQueryTest_Distance@@CAPEAVUClass@@PEB_W@Z) referenced in function "class UEnvQueryTest_Distance * __cdecl Cast<class UEnvQueryTest_Distance,class UEnvQueryTest>(class UEnvQueryTest *)" (??$Cast@VUEnvQueryTest_Distance@@VUEnvQueryTest@@@@YAPEAVUEnvQueryTest_Distance@@PEAVUEnvQueryTest@@@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "private: static class UClass * __cdecl UEnvQueryTest_Distance::GetPrivateStaticClass(wchar_t const *)" (?GetPrivateStaticClass@UEnvQueryTest_Distance@@CAPEAVUClass@@PEB_W@Z)
2>BehaviorRegistry.cpp.obj : error LNK2019: unresolved external symbol "public: __cdecl UEnvQueryTest_Distance::UEnvQueryTest_Distance(class FObjectInitializer const &)" (??0UEnvQueryTest_Distance@@QEAA@AEBVFObjectInitializer@@@Z) referenced in function "public: static void __cdecl BehaviorRegistry::FindCoverAttackSpot(class FString,float,float,float)" (?FindCoverAttackSpot@BehaviorRegistry@@SAXVFString@@MMM@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "public: __cdecl UEnvQueryTest_Distance::UEnvQueryTest_Distance(class FObjectInitializer const &)" (??0UEnvQueryTest_Distance@@QEAA@AEBVFObjectInitializer@@@Z)
2>BehaviorRegistry.cpp.obj : error LNK2019: unresolved external symbol "public: __cdecl UEnvQueryTest_Dot_Exposed::UEnvQueryTest_Dot_Exposed(class FObjectInitializer const &)" (??0UEnvQueryTest_Dot_Exposed@@QEAA@AEBVFObjectInitializer@@@Z) referenced in function "public: static void __cdecl BehaviorRegistry::FindCoverAttackSpot(class FString,float,float,float)" (?FindCoverAttackSpot@BehaviorRegistry@@SAXVFString@@MMM@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "public: __cdecl UEnvQueryTest_Dot_Exposed::UEnvQueryTest_Dot_Exposed(class FObjectInitializer const &)" (??0UEnvQueryTest_Dot_Exposed@@QEAA@AEBVFObjectInitializer@@@Z)
2>BehaviorRegistry.cpp.obj : error LNK2001: unresolved external symbol "private: static class TMap<class FString,class UBehaviorTree *,class FDefaultSetAllocator,struct TDefaultMapKeyFuncs<class FString,class UBehaviorTree *,0> > BehaviorRegistry::behaviors" (?behaviors@BehaviorRegistry@@0V?$TMap@VFString@@PEAVUBehaviorTree@@VFDefaultSetAllocator@@U?$TDefaultMapKeyFuncs@VFString@@PEAVUBehaviorTree@@$0A@@@@@A)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "private: static class TMap<class FString,class UBehaviorTree *,class FDefaultSetAllocator,struct TDefaultMapKeyFuncs<class FString,class UBehaviorTree *,0> > BehaviorRegistry::behaviors" (?behaviors@BehaviorRegistry@@0V?$TMap@VFString@@PEAVUBehaviorTree@@VFDefaultSetAllocator@@U?$TDefaultMapKeyFuncs@VFString@@PEAVUBehaviorTree@@$0A@@@@@A)
2>BehaviorRegistry.cpp.obj : error LNK2001: unresolved external symbol "private: static class TMap<class FString,class UEnvQuery *,class FDefaultSetAllocator,struct TDefaultMapKeyFuncs<class FString,class UEnvQuery *,0> > BehaviorRegistry::queries" (?queries@BehaviorRegistry@@0V?$TMap@VFString@@PEAVUEnvQuery@@VFDefaultSetAllocator@@U?$TDefaultMapKeyFuncs@VFString@@PEAVUEnvQuery@@$0A@@@@@A)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "private: static class TMap<class FString,class UEnvQuery *,class FDefaultSetAllocator,struct TDefaultMapKeyFuncs<class FString,class UEnvQuery *,0> > BehaviorRegistry::queries" (?queries@BehaviorRegistry@@0V?$TMap@VFString@@PEAVUEnvQuery@@VFDefaultSetAllocator@@U?$TDefaultMapKeyFuncs@VFString@@PEAVUEnvQuery@@$0A@@@@@A)
2>GuardSensory.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl IGameplayTaskOwnerInterface::OnGameplayTaskActivated(class UGameplayTask &)" (?OnGameplayTaskActivated@IGameplayTaskOwnerInterface@@UEAAXAEAVUGameplayTask@@@Z)
2>NPC.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl IGameplayTaskOwnerInterface::OnGameplayTaskActivated(class UGameplayTask &)" (?OnGameplayTaskActivated@IGameplayTaskOwnerInterface@@UEAAXAEAVUGameplayTask@@@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl IGameplayTaskOwnerInterface::OnGameplayTaskActivated(class UGameplayTask &)" (?OnGameplayTaskActivated@IGameplayTaskOwnerInterface@@UEAAXAEAVUGameplayTask@@@Z)
2>GuardSensory.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl IGameplayTaskOwnerInterface::OnGameplayTaskDeactivated(class UGameplayTask &)" (?OnGameplayTaskDeactivated@IGameplayTaskOwnerInterface@@UEAAXAEAVUGameplayTask@@@Z)
2>NPC.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl IGameplayTaskOwnerInterface::OnGameplayTaskDeactivated(class UGameplayTask &)" (?OnGameplayTaskDeactivated@IGameplayTaskOwnerInterface@@UEAAXAEAVUGameplayTask@@@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl IGameplayTaskOwnerInterface::OnGameplayTaskDeactivated(class UGameplayTask &)" (?OnGameplayTaskDeactivated@IGameplayTaskOwnerInterface@@UEAAXAEAVUGameplayTask@@@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl UEnvQueryTest_Dot::RunTest(struct FEnvQueryInstance &)const " (?RunTest@UEnvQueryTest_Dot@@MEBAXAEAUFEnvQueryInstance@@@Z)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual class FText __cdecl UEnvQueryTest_Dot::GetDescriptionTitle(void)const " (?GetDescriptionTitle@UEnvQueryTest_Dot@@MEBA?AVFText@@XZ)
2>Bounty.generated.cpp.obj : error LNK2001: unresolved external symbol "protected: virtual class FText __cdecl UEnvQueryTest_Dot::GetDescriptionDetails(void)const " (?GetDescriptionDetails@UEnvQueryTest_Dot@@MEBA?AVFText@@XZ)
And so on. Is this because the classes I’m trying to use are not exposed? Am I correct in my suspicion that I will have to fork the engine, expose the appropriate classes in AIModule, and then rebuild? Or is there an easier way to make environment queries runtime-editable from c++? Or is my approach completely wrong?