#ifndef ENEMY_WORLD_STATE_HPP #define ENEMY_WORLD_STATE_HPP #include "goap/goal.hpp" #include "unit_world_state.hpp" #include #include #include namespace gd = godot; class EntityHealth; class EnemyWorldState : public UnitWorldState { GDCLASS(EnemyWorldState, UnitWorldState); static void _bind_methods(); public: virtual void _ready() override; virtual void _process(double) override; void on_awareness_entered(gd::Node3D *node); void on_awareness_exited(gd::Node3D *node); void on_damaged(EntityHealth *, int, Unit *source); /*! Select the target with the highest priority and return it. * Assigns the priority of found target to out_priority. * \param out_priority Assigned to highest found priority, cannot be nullptr. */ Unit *select_target_from_known_with_priority(float *out_priority); //! Shorthand for select_target_from_known_with_priority(nullptr) Unit *select_target_from_known(); private: void queue_select_and_set_target(); void add_aware_unit(Unit *unit); void remove_aware_unit(Unit *unit); void select_and_set_target(); void on_aware_unit_death(Unit *, Unit *dead_entity); float calculate_priority(Unit *target); gd::Ref get_goal_for_target(Unit *unit); void try_set_target(Unit *target); void set_available_goals_inspector(gd::Array array); gd::Array get_available_goals_inspector() const; private: gd::Callable aware_unit_death{callable_mp(this, &EnemyWorldState::on_aware_unit_death)}; gd::Vector> available_goals{}; gd::Vector known_enemies{}; bool select_and_set_target_on_process{false}; gd::Ref last_goal{}; gd::Area3D *awareness_area{nullptr}; EntityHealth *health{nullptr}; }; #endif // !ENEMY_WORLD_STATE_HPP