From 6b7ca195ee81f58d6cae1f33d8890c4a147aa95a Mon Sep 17 00:00:00 2001 From: Sara Date: Thu, 29 Jan 2026 17:28:06 +0100 Subject: [PATCH] feat: NPC units drop demo packs --- modules/wave_survival/npc_unit.cpp | 25 +++++++++++++++++----- modules/wave_survival/npc_unit.h | 5 ++++- project/objects/units/unit_4_wretched.tscn | 14 ++++++------ 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/modules/wave_survival/npc_unit.cpp b/modules/wave_survival/npc_unit.cpp index 3f9f47aa..582dc525 100644 --- a/modules/wave_survival/npc_unit.cpp +++ b/modules/wave_survival/npc_unit.cpp @@ -4,11 +4,13 @@ #include "map_region.h" #include "patrol_path.h" #include "player_detector.h" +#include "scene/resources/packed_scene.h" 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"); + BIND_HPROPERTY(Variant::OBJECT, drop_on_clear, PROPERTY_HINT_RESOURCE_TYPE, "PackedScene"); } void NpcUnit::remove_npc(EnemyBody *npc) { @@ -18,18 +20,23 @@ void NpcUnit::remove_npc(EnemyBody *npc) { npc->set_global_transform(tf); } -void NpcUnit::on_npc_death() { +void NpcUnit::on_npc_death(EnemyBody *npc) { Vector::Size living{ this->npcs.size() }; - // remove any dead npcs from the list - // leaving their bodies as separate nodes part of the tree for (Vector::Size i{ 0 }; i < this->npcs.size(); ++i) { EnemyBody *npc{ this->npcs[i] }; if (npc->get_health()->get_health() <= 0) { --living; } } - // remove unit from world once all npcs are dead + // all member NPCs are dead, remove self (leaving NPC bodies) and drop reward for player if (living == 0) { + if (this->drop_on_clear.is_valid()) { + Node *node{ this->drop_on_clear->instantiate() }; + if (Node3D * node3d{ cast_to(node) }) { + node3d->set_position(npc->get_global_position()); + this->get_parent()->add_child(node3d); + } + } for (EnemyBody *npc : this->npcs) { remove_npc(npc); } @@ -63,7 +70,7 @@ void NpcUnit::ready() { 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)); + health->connect(HealthStatus::sig_death, callable_mp(this, &self_type::on_npc_death).bind(npc)); } } } @@ -123,3 +130,11 @@ void NpcUnit::set_region(MapRegion *region) { MapRegion *NpcUnit::get_region() const { return this->region; } + +void NpcUnit::set_drop_on_clear(Ref object) { + this->drop_on_clear = object; +} + +Ref NpcUnit::get_drop_on_clear() const { + return this->drop_on_clear; +} diff --git a/modules/wave_survival/npc_unit.h b/modules/wave_survival/npc_unit.h index 6140b233..6fb32bda 100644 --- a/modules/wave_survival/npc_unit.h +++ b/modules/wave_survival/npc_unit.h @@ -11,7 +11,7 @@ class NpcUnit : public Node3D { GDCLASS(NpcUnit, Node3D); static void _bind_methods(); void remove_npc(EnemyBody *unit); - void on_npc_death(); + void on_npc_death(EnemyBody *npc); void on_npc_awareness_changed(bool seen); void child_added(Node *node); void enter_tree(); @@ -28,6 +28,8 @@ public: float get_patrol_speed() const; void set_region(MapRegion *region); MapRegion *get_region() const; + void set_drop_on_clear(Ref object); + Ref get_drop_on_clear() const; private: bool aware_of_player{ false }; @@ -35,6 +37,7 @@ private: PatrolPath *patrol_path{ nullptr }; float patrol_speed{ 1.f }; MapRegion *region{ nullptr }; + Ref drop_on_clear{}; }; #endif // !NPC_UNIT_H diff --git a/project/objects/units/unit_4_wretched.tscn b/project/objects/units/unit_4_wretched.tscn index 92b484da..ca6cd386 100644 --- a/project/objects/units/unit_4_wretched.tscn +++ b/project/objects/units/unit_4_wretched.tscn @@ -1,18 +1,20 @@ -[gd_scene load_steps=2 format=3 uid="uid://5hg5eirw7v8n"] +[gd_scene format=3 uid="uid://5hg5eirw7v8n"] +[ext_resource type="PackedScene" uid="uid://cclghy01gblif" path="res://objects/pickups/demo_pack_pickup.tscn" id="1_6gvav"] [ext_resource type="PackedScene" uid="uid://dqlqgk1veyos8" path="res://objects/enemies/enemy_wretched.tscn" id="1_l77gx"] -[node name="NpcUnit" type="NpcUnit"] +[node name="NpcUnit" type="NpcUnit" unique_id=209119201] patrol_speed = 3.0 +drop_on_clear = ExtResource("1_6gvav") -[node name="EnemyWretched" parent="." instance=ExtResource("1_l77gx")] +[node name="EnemyWretched" parent="." unique_id=589775425 instance=ExtResource("1_l77gx")] transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, -1.1853347, 0.023195954, -0.8597343) -[node name="EnemyWretched5" parent="." instance=ExtResource("1_l77gx")] +[node name="EnemyWretched5" parent="." unique_id=833864271 instance=ExtResource("1_l77gx")] transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0.30714047, 0.023195954, 0.58812845) -[node name="EnemyWretched6" parent="." instance=ExtResource("1_l77gx")] +[node name="EnemyWretched6" parent="." unique_id=857064194 instance=ExtResource("1_l77gx")] transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0.05460906, 0.023195954, -1.4555124) -[node name="EnemyWretched2" parent="." instance=ExtResource("1_l77gx")] +[node name="EnemyWretched2" parent="." unique_id=80775110 instance=ExtResource("1_l77gx")] transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 1.3425274, 0.023196908, -0.9988682)