112 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.3 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);
 | 
						|
	callable_mp(cast_to<Node>(this->region), &Node::add_child).call_deferred(unit_3d, false, INTERNAL_MODE_DISABLED);
 | 
						|
	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;
 | 
						|
}
 |