79 lines
2.7 KiB
C++
79 lines
2.7 KiB
C++
#include "projectile_pool.hpp"
|
|
#include "projectile.hpp"
|
|
#include "weapon_data.hpp"
|
|
#include <godot_cpp/classes/scene_state.hpp>
|
|
#include <godot_cpp/variant/utility_functions.hpp>
|
|
|
|
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<WeaponData> 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<PackedScene> 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<Projectile>(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;
|
|
}
|
|
}
|