diff --git a/modules/wave_survival/enemy_body.cpp b/modules/wave_survival/enemy_body.cpp index d8bccc89..8d9d92ba 100644 --- a/modules/wave_survival/enemy_body.cpp +++ b/modules/wave_survival/enemy_body.cpp @@ -6,6 +6,15 @@ void EnemyBody::_bind_methods() { ClassDB::bind_method(D_METHOD("set_movement_direction", "direction"), &self_type::set_movement_direction); } +void EnemyBody::on_child_added(Node *node) { + if (StateMachine *fsm{ cast_to(node) }) { + this->fsm = fsm; + } + if (NavigationAgent3D *nav{ cast_to(node) }) { + this->nav = nav; + } +} + void EnemyBody::ready() { this->fsm = cast_to(get_node(NodePath("%StateMachine"))); this->nav = cast_to(get_node(NodePath("%NavigationAgent3D"))); @@ -50,6 +59,10 @@ NpcUnit *EnemyBody::get_unit() const { return this->unit; } +HealthStatus *EnemyBody::get_health() const { + return this->health; +} + NavigationAgent3D *EnemyBody::get_nav() const { return this->nav; } diff --git a/modules/wave_survival/enemy_body.h b/modules/wave_survival/enemy_body.h index 3949c109..2ff1016c 100644 --- a/modules/wave_survival/enemy_body.h +++ b/modules/wave_survival/enemy_body.h @@ -10,6 +10,7 @@ class NpcUnit; class EnemyBody : public CharacterBody3D { GDCLASS(EnemyBody, CharacterBody3D); static void _bind_methods(); + void on_child_added(Node *node); void ready(); void physics_process(double delta); @@ -20,6 +21,7 @@ public: void set_unit(NpcUnit *unit); NpcUnit *get_unit() const; + HealthStatus *get_health() const; NavigationAgent3D *get_nav() const; void set_movement_speed(float value); float get_movement_speed() const; @@ -33,6 +35,7 @@ private: StateMachine *fsm{ nullptr }; NpcUnit *unit{ nullptr }; + HealthStatus *health{ nullptr }; NavigationAgent3D *nav{ nullptr }; Vector2 unit_offset{ 0, 0 }; }; diff --git a/modules/wave_survival/map_region.cpp b/modules/wave_survival/map_region.cpp index e266b2f9..ab1c9552 100644 --- a/modules/wave_survival/map_region.cpp +++ b/modules/wave_survival/map_region.cpp @@ -1,7 +1,45 @@ #include "map_region.h" +#include "enemy_body.h" String const MapRegion::sig_phase_changed{ "phase_changed" }; void MapRegion::_bind_methods() { ADD_SIGNAL(MethodInfo(sig_phase_changed, PropertyInfo(Variant::BOOL, "hunt_phase"))); } + +void MapRegion::on_node_entered(Node *node) { + if (EnemyBody * body{ cast_to(node) }) { + if (!this->units.has(body->get_unit())) { + body->get_unit()->set_region(this); + } + } +} + +void MapRegion::ready() { + connect("body_entered", callable_mp(this, &self_type::on_node_entered)); +} + +void MapRegion::_notification(int what) { + if (Engine::get_singleton()->is_editor_hint()) { + return; + } + switch (what) { + default: + return; + case NOTIFICATION_READY: + ready(); + return; + } +} + +void MapRegion::register_unit(NpcUnit *unit) { + if (!this->units.has(unit)) { + this->units.insert(unit); + } +} + +void MapRegion::remove_unit(NpcUnit *unit) { + if (this->units.has(unit)) { + this->units.erase(unit); + } +} diff --git a/modules/wave_survival/map_region.h b/modules/wave_survival/map_region.h index 01ff6cf2..663e55ea 100644 --- a/modules/wave_survival/map_region.h +++ b/modules/wave_survival/map_region.h @@ -1,15 +1,27 @@ #ifndef MAP_REGION_H #define MAP_REGION_H +#include "core/templates/hash_set.h" +#include "npc_unit.h" #include "scene/3d/physics/area_3d.h" class MapRegion : public Area3D { GDCLASS(MapRegion, Area3D); static void _bind_methods(); + void on_node_entered(Node *node); + void ready(); + +protected: + void _notification(int what); + +public: + void register_unit(NpcUnit *unit); + void remove_unit(NpcUnit *unit); private: float awareness{ 0.f }; bool hunt_phase{ false }; + HashSet units{ nullptr }; public: static String const sig_phase_changed; diff --git a/modules/wave_survival/npc_unit.cpp b/modules/wave_survival/npc_unit.cpp index 7111be73..9df31166 100644 --- a/modules/wave_survival/npc_unit.cpp +++ b/modules/wave_survival/npc_unit.cpp @@ -1,6 +1,7 @@ #include "npc_unit.h" #include "enemy_body.h" #include "macros.h" +#include "map_region.h" #include "patrol_path.h" #include "player_detector.h" @@ -63,3 +64,18 @@ void NpcUnit::set_patrol_speed(float speed) { float NpcUnit::get_patrol_speed() const { return this->patrol_speed; } + +void NpcUnit::set_region(MapRegion *region) { + if (this->region == region) { + return; + } + if (this->region != nullptr) { + this->region->remove_unit(this); + } + this->region = region; + region->register_unit(this); +} + +MapRegion *NpcUnit::get_region() const { + return this->region; +} diff --git a/modules/wave_survival/npc_unit.h b/modules/wave_survival/npc_unit.h index 6f649912..79d6db23 100644 --- a/modules/wave_survival/npc_unit.h +++ b/modules/wave_survival/npc_unit.h @@ -5,6 +5,7 @@ class StateMachine; class EnemyBody; class PatrolPath; +class MapRegion; class NpcUnit : public Node3D { GDCLASS(NpcUnit, Node3D); @@ -22,12 +23,15 @@ public: bool is_aware_of_player() const; //!< becomes true when any individual in the unit sees the player. void set_patrol_speed(float value); float get_patrol_speed() const; + void set_region(MapRegion *region); + MapRegion *get_region() const; private: bool aware_of_player{ false }; Vector npcs{}; PatrolPath *patrol_path{ nullptr }; float patrol_speed{ 1.f }; + MapRegion *region{ nullptr }; }; #endif // !NPC_UNIT_H diff --git a/modules/wave_survival/register_types.cpp b/modules/wave_survival/register_types.cpp index 36c120c9..41a6231c 100644 --- a/modules/wave_survival/register_types.cpp +++ b/modules/wave_survival/register_types.cpp @@ -9,6 +9,7 @@ #include "wave_survival/hitbox.h" #include "wave_survival/hitscan_muzzle.h" #include "wave_survival/interactable.h" +#include "wave_survival/map_region.h" #include "wave_survival/muzzle_effect.h" #include "wave_survival/npc_unit.h" #include "wave_survival/patrol_path.h" @@ -22,7 +23,6 @@ #include "wave_survival/state.h" #include "wave_survival/state_machine.h" #include "wave_survival/weapon_base.h" -#include "wave_survival/map_region.h" #include "wave_survival/weapon_inventory.h" #include "wave_survival/weapons/revolver.h" #include "wave_survival/weapons/rifle.h"