112 lines
3.2 KiB
C++
112 lines
3.2 KiB
C++
#include "enemy_spawner.h"
|
|
#include "core/io/resource.h"
|
|
#include "core/object/object.h"
|
|
#include "macros.h"
|
|
#include "map_region.h"
|
|
#include "npc_unit.h"
|
|
#include "patrol_path.h"
|
|
#include "scene/resources/packed_scene.h"
|
|
|
|
void SpawnData::_bind_methods() {
|
|
BIND_HPROPERTY(Variant::DICTIONARY, difficulty_spawns, PROPERTY_HINT_DICTIONARY_TYPE, vformat("int;%s/%s:PackedScene", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE));
|
|
}
|
|
|
|
void SpawnData::set_difficulty_spawns(Dictionary dict) {
|
|
this->difficulty_spawns.clear();
|
|
for (KeyValue<Variant, Variant> const &kvp : dict) {
|
|
Ref<PackedScene> scene{ kvp.value };
|
|
if (scene.is_null() || !scene.is_valid()) {
|
|
continue;
|
|
} else if (!kvp.key.is_num()) {
|
|
continue;
|
|
} else {
|
|
this->difficulty_spawns.insert(kvp.key, scene);
|
|
}
|
|
}
|
|
}
|
|
|
|
Dictionary SpawnData::get_difficulty_spawns() const {
|
|
Dictionary r{};
|
|
for (KeyValue<int, Ref<PackedScene>> const &kvp : this->difficulty_spawns) {
|
|
r.set(kvp.key, kvp.value);
|
|
}
|
|
return r;
|
|
}
|
|
|
|
void EnemySpawner::_bind_methods() {
|
|
BIND_HPROPERTY(Variant::OBJECT, spawn_data, PROPERTY_HINT_RESOURCE_TYPE, "SpawnData");
|
|
BIND_HPROPERTY(Variant::OBJECT, patrol_path, PROPERTY_HINT_NODE_TYPE, "PatrolPath");
|
|
}
|
|
|
|
void EnemySpawner::on_phase_change(bool hunt) {
|
|
Ref<PackedScene> scene{ Ref<PackedScene>() };
|
|
int const idx{ this->region->get_current_difficulty() };
|
|
if (this->spawn_data->difficulty_spawns.has(idx)) {
|
|
scene = this->spawn_data->difficulty_spawns[idx];
|
|
}
|
|
if (!scene.is_valid()) {
|
|
print_error("EnemySpawner::on_phase_change: Spawn data scene is invalid");
|
|
return;
|
|
}
|
|
Node *instantiated{ scene->instantiate() };
|
|
if (instantiated == nullptr) {
|
|
print_error("EnemySpawner::on_phase_change: Spawn data instantiated a nullptr node");
|
|
return;
|
|
}
|
|
NpcUnit *unit_3d{ cast_to<NpcUnit>(instantiated) };
|
|
if (unit_3d == nullptr) {
|
|
instantiated->queue_free();
|
|
print_error("EnemySpawner::on_phase_change: Spawn data instantiated an invalid unit that cannot be cast to NpcUnit");
|
|
return;
|
|
}
|
|
unit_3d->set_patrol_path(this->patrol_path);
|
|
add_child(unit_3d);
|
|
unit_3d->set_global_transform(this->get_global_transform());
|
|
}
|
|
|
|
void EnemySpawner::ready() {
|
|
if (MapRegion * region{ cast_to<MapRegion>(this->get_parent()) }) {
|
|
this->region = region;
|
|
region->connect(MapRegion::sig_phase_changed, callable_mp(this, &self_type::on_phase_change));
|
|
} else {
|
|
print_error("EnemySpawner::ready: Failed to find region in parent");
|
|
}
|
|
if (!this->spawn_data.is_valid()) {
|
|
this->spawn_data = ResourceLoader::load("res://data/spawn_data/default.tres");
|
|
}
|
|
if (this->spawn_data.is_valid()) {
|
|
on_phase_change(false);
|
|
} else {
|
|
print_error("EnemySpawner::ready: No spawn data found, default spawn data is invalid, consider setting up a default spawn data");
|
|
}
|
|
}
|
|
|
|
void EnemySpawner::_notification(int what) {
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
return;
|
|
}
|
|
switch (what) {
|
|
default:
|
|
return;
|
|
case NOTIFICATION_READY:
|
|
ready();
|
|
return;
|
|
}
|
|
}
|
|
|
|
void EnemySpawner::set_spawn_data(Ref<SpawnData> data) {
|
|
this->spawn_data = data;
|
|
}
|
|
|
|
Ref<SpawnData> EnemySpawner::get_spawn_data() const {
|
|
return this->spawn_data;
|
|
}
|
|
|
|
void EnemySpawner::set_patrol_path(PatrolPath *path) {
|
|
this->patrol_path = path;
|
|
}
|
|
|
|
PatrolPath *EnemySpawner::get_patrol_path() const {
|
|
return this->patrol_path;
|
|
}
|