#ifndef ENEMY_BODY_H #define ENEMY_BODY_H #include "scene/3d/navigation/navigation_agent_3d.h" #include "scene/3d/physics/character_body_3d.h" #include "wave_survival/health_status.h" #include "wave_survival/state.h" #include "wave_survival/state_machine.h" class NpcUnit; class AnimationPlayer; class PatrolPath; class PlayerDetector; class EnemyBody : public CharacterBody3D { GDCLASS(EnemyBody, CharacterBody3D); static void _bind_methods(); void on_child_added(Node *node); void ready(); void physics_process(double delta); protected: void _notification(int what); public: void set_max_speed(float speed); float get_max_speed() const; void set_movement_direction(Vector2 direction); void set_unit(NpcUnit *unit); NpcUnit *get_unit() const; HealthStatus *get_health() const; NavigationAgent3D *get_nav() const; AnimationPlayer *get_anim() const; StateMachine *get_fsm() const; PlayerDetector *get_detector() const; void set_movement_speed(float value); float get_movement_speed() const; void set_unit_offset(Vector2 offset); Vector2 get_unit_offset() const; Vector3 get_unit_offset_3d() const; private: float max_speed{ 4.f }; float movement_speed{ 1.f }; Vector2 movement_direction{ 0, 0 }; StateMachine *fsm{ nullptr }; NpcUnit *unit{ nullptr }; HealthStatus *health{ nullptr }; NavigationAgent3D *nav{ nullptr }; AnimationPlayer *anim{ nullptr }; PlayerDetector *detector{ nullptr }; Vector2 unit_offset{ 0, 0 }; }; /* ============================== STATES ============================== */ class EnemyState : public State { GDCLASS(EnemyState, State); static void _bind_methods() {} public: void set_target(Node *node) override; NpcUnit *get_unit() const; NavigationAgent3D *get_nav() const; AnimationPlayer *get_anim() const; EnemyBody *get_body() const; private: EnemyBody *body{ nullptr }; }; class EnemyPatrolState : public EnemyState { GDCLASS(EnemyPatrolState, EnemyState); static void _bind_methods() {} void set_patrol_target(Vector3 path_point); void on_velocity_calculated(Vector3 direction); public: virtual void enter_state() override; virtual void process(double delta) override; virtual void exit_state() override; private: int path_point{ 0 }; PatrolPath *path{ nullptr }; Callable mp_on_velocity_calculated{ callable_mp(this, &self_type::on_velocity_calculated) }; }; class EnemyChaseState : public EnemyState { GDCLASS(EnemyChaseState, EnemyState); static void _bind_methods() {} public: virtual void enter_state() override; virtual void process(double delta) override; }; #endif // !ENEMY_BODY_H