diff --git a/modules/wave_survival/npc_unit.cpp b/modules/wave_survival/npc_unit.cpp index 9df31166..65156b24 100644 --- a/modules/wave_survival/npc_unit.cpp +++ b/modules/wave_survival/npc_unit.cpp @@ -8,6 +8,24 @@ void NpcUnit::_bind_methods() { BIND_HPROPERTY(Variant::OBJECT, patrol_path, PROPERTY_HINT_NODE_TYPE, "PatrolPath"); BIND_PROPERTY(Variant::FLOAT, patrol_speed); + BIND_HPROPERTY(Variant::OBJECT, region, PROPERTY_HINT_NODE_TYPE, "MapRegion"); +} + +void NpcUnit::on_npc_death() { + // remove any dead npcs from the list + // leaving their bodies as separate nodes part of the tree + for (EnemyBody *npc : this->npcs) { + if (npc->get_health()->get_health() <= 0) { + this->get_parent()->add_child(npc); + this->npcs.erase(npc); + break; + } + } + // remove unit from world once all npcs are dead + if (this->npcs.size() <= 0) { + this->set_region(nullptr); // de-register from region + this->queue_free(); + } } void NpcUnit::on_npc_awareness_changed(bool value) { @@ -22,9 +40,6 @@ void NpcUnit::child_added(Node *node) { npc->set_unit(this); Vector3 const offset{ npc->get_global_position() - get_global_position() }; npc->set_unit_offset({ offset.x, offset.z }); - if (PlayerDetector * detector{ cast_to(npc->get_node(NodePath("%PlayerDetector"))) }) { - detector->connect(PlayerDetector::sig_awareness_changed, callable_mp(this, &self_type::on_npc_awareness_changed)); - } } } @@ -32,7 +47,19 @@ void NpcUnit::enter_tree() { this->connect("child_entered_tree", callable_mp(this, &self_type::child_added)); } +void NpcUnit::ready() { + for (EnemyBody *npc : this->npcs) { + if (PlayerDetector * detector{ cast_to(npc->get_node(NodePath("%PlayerDetector"))) }) { + detector->connect(PlayerDetector::sig_awareness_changed, callable_mp(this, &self_type::on_npc_awareness_changed)); + } + if (HealthStatus * health{ npc->get_health() }) { + health->connect(HealthStatus::sig_death, callable_mp(this, &self_type::on_npc_death)); + } + } +} + void NpcUnit::_notification(int what) { + // only run in-game if (Engine::get_singleton()->is_editor_hint()) { return; } @@ -42,6 +69,9 @@ void NpcUnit::_notification(int what) { case NOTIFICATION_ENTER_TREE: enter_tree(); return; + case NOTIFICATION_READY: + ready(); + return; } } @@ -67,13 +97,17 @@ float NpcUnit::get_patrol_speed() const { void NpcUnit::set_region(MapRegion *region) { if (this->region == region) { - return; + return; // don't re-register } if (this->region != nullptr) { this->region->remove_unit(this); + this->region->disconnect(MapRegion::sig_phase_changed, callable_mp(this, &self_type::on_npc_awareness_changed)); } this->region = region; - region->register_unit(this); + if (region != nullptr) { + region->register_unit(this); + region->connect(MapRegion::sig_phase_changed, callable_mp(this, &self_type::on_npc_awareness_changed)); + } } MapRegion *NpcUnit::get_region() const { diff --git a/modules/wave_survival/npc_unit.h b/modules/wave_survival/npc_unit.h index 79d6db23..142bd0f9 100644 --- a/modules/wave_survival/npc_unit.h +++ b/modules/wave_survival/npc_unit.h @@ -10,9 +10,11 @@ class MapRegion; class NpcUnit : public Node3D { GDCLASS(NpcUnit, Node3D); static void _bind_methods(); + void on_npc_death(); void on_npc_awareness_changed(bool seen); void child_added(Node *node); void enter_tree(); + void ready(); protected: void _notification(int what);