Browse Source
- Fixed frustrating bug in PooledComponentManager where member Subscribers was being used instead of ComponentManager Subscribers. The solution was to get rid of PooledComponentManager's Subscribers declaration - ComponentManager now only goes all the way with unsubscribing if there are entities left to unsubscribe - Fixed an apparent bug in EntityListSortAndRemoveDuplicates() and EntityListRemoveNonUniqueEntitiesInSuspect() where the iterator wouldn't be advanced on removal - Filled in InteractComponentManager and added PickupDirect() which puts a pickup straight into an entity's need (for testing purposes) - Added NeedTypes and AgentComponentManager interface to get an agent's specific need - Added InteractPickupTask, which uses the PickupDirect command on a TargetEntity - FindResource now marks the found resource as the TargetEntity - WorldResourceLocator now stores an Entity and a ResourceType on the Resource, facilitating Pickups as well as making the zero position shenanigans go away - Got all the Sublime project working dirs sorted out and added a bunch of helpful build systems (for me, at least) - Added my TODO file to remember where I left off and suchcombatComponentRefactor

30 changed files with 632 additions and 91 deletions
@ -0,0 +1,17 @@ |
|||
TODO |
|||
|
|||
Soak test editor - after ~1 hour it was looking pretty glitchy |
|||
|
|||
What does agent component manager do with triggers once plan is done? How to know plan is done? |
|||
|
|||
statics don't work well with hot reloading |
|||
|
|||
FragmentedPool crashed during in-editor compile hotreload |
|||
|
|||
Still hitting TestMovementComponent segfault. Need a way to detect when an entity is destroyed outside GV control |
|||
Added code to EndPlay() which unsubscribes shit manually |
|||
|
|||
Play with Polyvox chunk scale |
|||
|
|||
**** LEFT OFF AT: |
|||
InteractTask added, it should be hooked up and working |
Binary file not shown.
@ -0,0 +1,18 @@ |
|||
#pragma once |
|||
|
|||
#include "../../entityComponentSystem/EntityTypes.hpp" |
|||
#include "../../world/Position.hpp" |
|||
|
|||
namespace gv |
|||
{ |
|||
/* --MovementManager--
|
|||
This was needed so that I could have a heavily Unreal-specific class (TestMovementComponent) without |
|||
needing to compromise the Galavant lib. I'll probably think of a better way to do this eventually |
|||
*/ |
|||
class MovementManager |
|||
{ |
|||
public: |
|||
virtual ~MovementManager() = default; |
|||
virtual void PathEntitiesTo(const EntityList& entities, const PositionList& positions) = 0; |
|||
}; |
|||
} |
@ -0,0 +1,13 @@ |
|||
#pragma once |
|||
|
|||
namespace gv |
|||
{ |
|||
enum class NeedType : unsigned int |
|||
{ |
|||
None = 0, |
|||
|
|||
Hunger, |
|||
|
|||
NeedType_Count |
|||
}; |
|||
} |
@ -0,0 +1,48 @@ |
|||
#include "InteractTasks.hpp" |
|||
|
|||
#include "util/Logging.hpp" |
|||
#include "world/Position.hpp" |
|||
#include "world/WorldResourceLocator.hpp" |
|||
|
|||
namespace gv |
|||
{ |
|||
void InteractPickupTask::Initialize(InteractComponentManager* newInteractManager) |
|||
{ |
|||
InteractManager = newInteractManager; |
|||
} |
|||
|
|||
bool InteractPickupTask::StateMeetsPreconditions(const gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) const |
|||
{ |
|||
return state.SourceAgent.TargetEntity && InteractManager && |
|||
InteractManager->IsSubscribed(state.SourceAgent.TargetEntity); |
|||
} |
|||
|
|||
void InteractPickupTask::ApplyStateChange(gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) |
|||
{ |
|||
// No WorldState records needs yet
|
|||
} |
|||
|
|||
Htn::TaskExecuteStatus InteractPickupTask::Execute(gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) |
|||
{ |
|||
// TODO: should the PlanComponentManager call this before executing any task?
|
|||
if (StateMeetsPreconditions(state, parameters)) |
|||
{ |
|||
if (InteractManager->PickupDirect(state.SourceAgent.TargetEntity, |
|||
state.SourceAgent.SourceEntity)) |
|||
{ |
|||
LOGD << "Found resource at " << state.SourceAgent.TargetPosition; |
|||
Htn::TaskExecuteStatus status{Htn::TaskExecuteStatus::ExecutionStatus::Succeeded}; |
|||
return status; |
|||
} |
|||
} |
|||
else |
|||
LOGD << "State no longer matches preconditions"; |
|||
|
|||
LOGD << "Failed to pickup"; |
|||
Htn::TaskExecuteStatus status{Htn::TaskExecuteStatus::ExecutionStatus::Failed}; |
|||
return status; |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
#pragma once |
|||
|
|||
#include "../../../ai/htn/HTNTypes.hpp" |
|||
#include "../../../ai/htn/HTNTasks.hpp" |
|||
#include "../../../ai/WorldState.hpp" |
|||
|
|||
#include "../../InteractComponentManager.hpp" |
|||
|
|||
namespace gv |
|||
{ |
|||
// Parameters:
|
|||
// None
|
|||
// Dependent WorldState:
|
|||
// TargetEntity
|
|||
class InteractPickupTask : public Htn::PrimitiveTask |
|||
{ |
|||
private: |
|||
InteractComponentManager* InteractManager; |
|||
public: |
|||
InteractPickupTask() = default; |
|||
virtual ~InteractPickupTask() = default; |
|||
|
|||
void Initialize(InteractComponentManager* newInteractManager); |
|||
virtual bool StateMeetsPreconditions(const gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) const; |
|||
virtual void ApplyStateChange(gv::WorldState& state, const Htn::ParameterList& parameters); |
|||
virtual Htn::TaskExecuteStatus Execute(gv::WorldState& state, |
|||
const Htn::ParameterList& parameters); |
|||
}; |
|||
} |
@ -0,0 +1,126 @@ |
|||
#include "MovementTasks.hpp" |
|||
|
|||
#include "util/Logging.hpp" |
|||
#include "world/Position.hpp" |
|||
#include "world/WorldResourceLocator.hpp" |
|||
|
|||
namespace gv |
|||
{ |
|||
bool FindResourceTask::StateMeetsPreconditions(const gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) const |
|||
{ |
|||
return parameters.size() == 1 && parameters[0].Type == Htn::Parameter::ParamType::Int && |
|||
gv::WorldResourceLocator::ResourceExistsInWorld( |
|||
(gv::WorldResourceType)parameters[0].IntValue); |
|||
} |
|||
|
|||
void FindResourceTask::ApplyStateChange(gv::WorldState& state, const Htn::ParameterList& parameters) |
|||
{ |
|||
// TODO: Should this be the case? Should StateMeetsPreconditions find the position? This isn't
|
|||
// that much of a problem if ResourceLocator caches searches
|
|||
float manhattanTo = 0.f; |
|||
gv::WorldResourceLocator::Resource* resource = gv::WorldResourceLocator::FindNearestResource( |
|||
(gv::WorldResourceType)parameters[0].IntValue, state.SourceAgent.position, false, |
|||
manhattanTo); |
|||
if (resource) |
|||
{ |
|||
state.SourceAgent.TargetPosition = resource->position; |
|||
state.SourceAgent.TargetEntity = resource->entity; |
|||
} |
|||
} |
|||
|
|||
Htn::TaskExecuteStatus FindResourceTask::Execute(gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) |
|||
{ |
|||
float manhattanTo = 0.f; |
|||
gv::WorldResourceLocator::Resource* resource = gv::WorldResourceLocator::FindNearestResource( |
|||
(gv::WorldResourceType)parameters[0].IntValue, state.SourceAgent.position, false, |
|||
manhattanTo); |
|||
if (resource) |
|||
{ |
|||
LOGD << "Found resource at " << state.SourceAgent.TargetPosition; |
|||
// TODO: Execute and ApplyStateChange duplicate code
|
|||
state.SourceAgent.TargetPosition = resource->position; |
|||
state.SourceAgent.TargetEntity = resource->entity; |
|||
Htn::TaskExecuteStatus status{Htn::TaskExecuteStatus::ExecutionStatus::Succeeded}; |
|||
return status; |
|||
} |
|||
else |
|||
LOGD << "Couldn't find resource!"; |
|||
|
|||
LOGD << "Failed to find resource"; |
|||
Htn::TaskExecuteStatus status{Htn::TaskExecuteStatus::ExecutionStatus::Failed}; |
|||
return status; |
|||
} |
|||
|
|||
void MoveToTask::Initialize(MovementManager* newMovementManager) |
|||
{ |
|||
movementManager = newMovementManager; |
|||
} |
|||
|
|||
bool MoveToTask::StateMeetsPreconditions(const gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) const |
|||
{ |
|||
// We're good to move to a position as long as we have a target
|
|||
if (state.SourceAgent.TargetPosition) |
|||
return true; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
void MoveToTask::ApplyStateChange(gv::WorldState& state, const Htn::ParameterList& parameters) |
|||
{ |
|||
state.SourceAgent.position = state.SourceAgent.TargetPosition; |
|||
} |
|||
|
|||
Htn::TaskExecuteStatus MoveToTask::Execute(gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) |
|||
{ |
|||
if (movementManager) |
|||
{ |
|||
gv::EntityList entitiesToMove{state.SourceAgent.SourceEntity}; |
|||
std::vector<gv::Position> positions{state.SourceAgent.TargetPosition}; |
|||
LOGD << "Moving Ent[" << state.SourceAgent.SourceEntity << "] to " |
|||
<< state.SourceAgent.TargetPosition; |
|||
movementManager->PathEntitiesTo(entitiesToMove, positions); |
|||
Htn::TaskExecuteStatus status{Htn::TaskExecuteStatus::ExecutionStatus::Subscribe}; |
|||
return status; |
|||
} |
|||
|
|||
Htn::TaskExecuteStatus status{Htn::TaskExecuteStatus::ExecutionStatus::Failed}; |
|||
return status; |
|||
} |
|||
|
|||
void GetResourceTask::Initialize(FindResourceTask* newFindResourceTask, MoveToTask* newMoveToTask) |
|||
{ |
|||
FindResourceTaskRef.Initialize(newFindResourceTask); |
|||
MoveToTaskRef.Initialize(newMoveToTask); |
|||
} |
|||
|
|||
bool GetResourceTask::StateMeetsPreconditions(const gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) const |
|||
{ |
|||
// TODO: What is the purpose of the compound task checking preconditions if they'll be near
|
|||
// identical to the combined primitive task preconditions?
|
|||
bool parametersValid = |
|||
parameters.size() == 1 && parameters[0].Type == Htn::Parameter::ParamType::Int; |
|||
LOGD_IF(!parametersValid) << "GetResourceTask parameters invalid! Expected Int"; |
|||
return parametersValid; |
|||
} |
|||
|
|||
bool GetResourceTask::Decompose(Htn::TaskCallList& taskCallList, const gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) |
|||
{ |
|||
Htn::ParameterList findResourceParams = parameters; |
|||
Htn::ParameterList moveToParams; |
|||
|
|||
Htn::TaskCall FindResourceTaskCall{&FindResourceTaskRef, findResourceParams}; |
|||
Htn::TaskCall MoveToTaskCall{&MoveToTaskRef, moveToParams}; |
|||
|
|||
// TODO: Make it clear that users should only ever push to this list
|
|||
taskCallList.push_back(FindResourceTaskCall); |
|||
taskCallList.push_back(MoveToTaskCall); |
|||
|
|||
return true; |
|||
} |
|||
} |
@ -0,0 +1,64 @@ |
|||
#pragma once |
|||
|
|||
#include "../../../ai/htn/HTNTypes.hpp" |
|||
#include "../../../ai/htn/HTNTasks.hpp" |
|||
#include "../../../ai/WorldState.hpp" |
|||
#include "../MovementManager.hpp" |
|||
|
|||
namespace gv |
|||
{ |
|||
// Parameters:
|
|||
// [0]: Resource type (int)
|
|||
class FindResourceTask : public Htn::PrimitiveTask |
|||
{ |
|||
public: |
|||
FindResourceTask() = default; |
|||
virtual ~FindResourceTask() = default; |
|||
|
|||
void Initialize(); |
|||
virtual bool StateMeetsPreconditions(const gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) const; |
|||
virtual void ApplyStateChange(gv::WorldState& state, const Htn::ParameterList& parameters); |
|||
virtual Htn::TaskExecuteStatus Execute(gv::WorldState& state, |
|||
const Htn::ParameterList& parameters); |
|||
}; |
|||
|
|||
// Parameters:
|
|||
// None - Entity to move and target come from world state
|
|||
class MoveToTask : public Htn::PrimitiveTask |
|||
{ |
|||
private: |
|||
MovementManager* movementManager; |
|||
|
|||
public: |
|||
MoveToTask() = default; |
|||
virtual ~MoveToTask() = default; |
|||
|
|||
void Initialize(MovementManager* newMovementManager); |
|||
virtual bool StateMeetsPreconditions(const gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) const; |
|||
virtual void ApplyStateChange(gv::WorldState& state, const Htn::ParameterList& parameters); |
|||
virtual Htn::TaskExecuteStatus Execute(gv::WorldState& state, |
|||
const Htn::ParameterList& parameters); |
|||
}; |
|||
|
|||
// Parameters:
|
|||
// [0]: Resource type (int)
|
|||
class GetResourceTask : public Htn::CompoundTask |
|||
{ |
|||
private: |
|||
// Should this be how it is? Should tasks be singletons?
|
|||
Htn::Task FindResourceTaskRef; |
|||
Htn::Task MoveToTaskRef; |
|||
|
|||
public: |
|||
GetResourceTask() = default; |
|||
virtual ~GetResourceTask() = default; |
|||
|
|||
void Initialize(FindResourceTask* newFindResourceTask, MoveToTask* newMoveToTask); |
|||
virtual bool StateMeetsPreconditions(const gv::WorldState& state, |
|||
const Htn::ParameterList& parameters) const; |
|||
virtual bool Decompose(Htn::TaskCallList& taskCallList, const gv::WorldState& state, |
|||
const Htn::ParameterList& parameters); |
|||
}; |
|||
} |
Loading…
Reference in new issue