diff --git a/src/planner.cpp b/src/planner.cpp index 5520c65..4fe0f8c 100644 --- a/src/planner.cpp +++ b/src/planner.cpp @@ -2,7 +2,6 @@ #include "action.hpp" #include "global_world_state.hpp" #include "utils/godot_macros.h" -#include #include #include #include diff --git a/src/planner.hpp b/src/planner.hpp index 6fa4824..b197812 100644 --- a/src/planner.hpp +++ b/src/planner.hpp @@ -14,23 +14,6 @@ class CharacterActor; namespace goap { class GlobalWorldState; -struct State { - static State new_move_to(Vector3 location); - static State new_animate(StringName animation); - static State new_activate(Node *node); - enum Type { - STATE_MOVE_TO, - STATE_ANIMATE, - STATE_ACTIVATE - }; - State::Type type; - union { - Vector3 move_to; - StringName animate; - Node *activate; - }; -}; - class Goal : public Resource { GDCLASS(Goal, Resource); static void _bind_methods(); diff --git a/src/register_types.cpp b/src/register_types.cpp index 701e673..8a05f53 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -1,13 +1,14 @@ #include "register_types.h" #include "action.hpp" -#include "character_data.hpp" #include "character_actor.hpp" +#include "character_data.hpp" #include "enemy.hpp" #include "global_world_state.hpp" #include "health.hpp" #include "pellet_projectile.hpp" #include "planner.hpp" #include "projectile_pool.hpp" +#include "state.hpp" #include "tunnels_game_mode.hpp" #include "tunnels_game_state.hpp" #include "tunnels_player.hpp" @@ -57,6 +58,10 @@ void initialize_gdextension_types(ModuleInitializationLevel p_level) ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_abstract_class(); + ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class(); ClassDB::register_class(); } diff --git a/src/state.cpp b/src/state.cpp new file mode 100644 index 0000000..165c3e7 --- /dev/null +++ b/src/state.cpp @@ -0,0 +1,76 @@ +#include "state.hpp" +#include "character_actor.hpp" +#include "utils/godot_macros.h" + +namespace godot::goap { +State::~State() { + if(unlikely(this->type == STATE_ANIMATE)) + delete this->animate; +} + +State State::new_move_to(Node3D *node) { + return { + .type = State::Type::STATE_MOVE_TO, + .move_to = node + }; +} + +State State::new_animate(StringName animation) { + return { + .type = State::Type::STATE_ANIMATE, + .animate = new StringName(animation) + }; +} + +State State::new_activate(Node *node) { + return { + .type = State::Type::STATE_ACTIVATE, + .activate = node + }; +} + +bool State::is_complete(CharacterActor *context) const { + switch(this->type) { + default: + return true; + case STATE_MOVE_TO: + return context->get_global_position().is_equal_approx(this->move_to->get_global_position()); + case STATE_ANIMATE: + return false; // TODO: replace this with checks for animation completion + case STATE_ACTIVATE: + return false; // TODO: replace this with checks for object activation + } +} + +void StateArgs::_bind_methods() { +#define CLASSNAME StateArgs + GDPROPERTY(argument_property, Variant::STRING_NAME); +} + +State StateArgs::construct(Node *context) const { + return { .type = State::STATE_TYPE_MAX }; +} + +void StateArgs::set_argument_property(StringName var) { this->argument_property = var; } +StringName StateArgs::get_argument_property() const { return this->argument_property; } + +void MoveStateArgs::_bind_methods() {} + +State MoveStateArgs::construct(Node *context) const { + Node3D *node = Object::cast_to(context->call("get_" + this->argument_property)); + return State::new_move_to(node); +} + +void AnimateStateArgs::_bind_methods() {} + +State AnimateStateArgs::construct(Node *context) const { + return State::new_animate(context->call("get_" + this->argument_property)); +} + +void ActivateStateArgs::_bind_methods() {} + +State ActivateStateArgs::construct(Node *context) const { + Node *node = Object::cast_to(context->call("get_" + this->argument_property)); + return State::new_activate(node); +} +} diff --git a/src/state.hpp b/src/state.hpp new file mode 100644 index 0000000..8a7e528 --- /dev/null +++ b/src/state.hpp @@ -0,0 +1,65 @@ +#ifndef GOAP_STATE_HPP +#define GOAP_STATE_HPP + +#include +#include +#include +#include +#include + +namespace godot { class CharacterActor; } +namespace godot::goap { +struct State { + ~State(); + static State new_move_to(Node3D *location); + static State new_animate(StringName animation); + static State new_activate(Node *node); + + bool is_complete(CharacterActor *context) const; + + enum Type { + STATE_MOVE_TO, + STATE_ANIMATE, + STATE_ACTIVATE, + STATE_TYPE_MAX, + }; + State::Type type{STATE_TYPE_MAX}; + union { + Node3D* move_to; + StringName *animate; + Node *activate; + }; +}; + +class StateArgs : public Resource { + GDCLASS(StateArgs, Resource); + static void _bind_methods(); +public: + virtual State construct(Node *context) const; + void set_argument_property(StringName name); + StringName get_argument_property() const; + StringName argument_property; +}; + +class MoveStateArgs : public StateArgs { + GDCLASS(MoveStateArgs, StateArgs); + static void _bind_methods(); + virtual State construct(Node *context) const override; +}; + +class AnimateStateArgs : public StateArgs { + GDCLASS(AnimateStateArgs, StateArgs); + static void _bind_methods(); +public: + virtual State construct(Node *context) const override; +}; + +class ActivateStateArgs : public StateArgs { + GDCLASS(ActivateStateArgs, StateArgs); + static void _bind_methods(); +public: + virtual State construct(Node *context) const override; +}; +}; + +#endif // !GOAP_STATE_HPP