#include "projectile_pool.hpp" #include "projectile.hpp" #include "weapon_data.hpp" #include #include namespace godot { void ProjectilePool::_bind_methods() { #define CLASSNAME ProjectilePool } void ProjectilePool::_exit_tree() { for(Node3D *node : this->inactive) { node->queue_free(); } } void ProjectilePool::set_data(Ref value) { UtilityFunctions::print("ProjectilePool::set_data"); if(!this->data.is_null()) { this->active.clear(); for(Node3D *node : this->inactive) node->queue_free(); } this->data = value; if(!value.is_valid()) return; this->count = this->data->get_projectile_count() * this->data->get_rounds_per_second() * 2; for(size_t i{0}; i < this->count; ++i) this->inactive.push_back(this->instantiate_new()); } Node3D *ProjectilePool::claim_projectile() { Node3D *node{this->inactive[0]}; this->add_child(node); this->inactive.erase(node); this->active.push_back(node); if(inactive.is_empty()) { size_t const new_count = this->count + this->data->get_projectile_count() * this->data->get_rounds_per_second() * 2; for(size_t i{this->count}; i < new_count; ++i) this->inactive.push_back(this->instantiate_new()); this->count = new_count; } if(node == nullptr) UtilityFunctions::push_error("Failed to spawn node"); return node; } void ProjectilePool::return_projectile(Node3D *node) { if(this->active.has(node)) { this->remove_child(node); this->active.erase(node); this->inactive.push_back(node); } else { // leftover from previous weapon, free node->queue_free(); } } Node3D *ProjectilePool::instantiate_new(bool active) { Ref scene = this->data->get_projectile_scene(); if(!scene.is_valid() || !ClassDB::is_parent_class(scene->get_state()->get_node_type(0), "Projectile")) { UtilityFunctions::push_error("Attempt to instantiate pooled projectile failed, scene is ", scene.is_valid() ? (scene->get_state()->get_node_type(0) + String(" not inherited from Projectile")) : "not a valid scene resource"); return nullptr; } Projectile *projectile = Object::cast_to(this->data->get_projectile_scene()->instantiate()); if(!projectile) { UtilityFunctions::push_error("Failed to instantiate projectile"); return nullptr; } if(active) this->add_child(projectile); projectile->set_weapon_data(this->data); projectile->set_projectile_pool(this); projectile->set_as_top_level(true); return projectile; } }