#include "pellet_projectile.hpp" #include "health.hpp" #include "utils/godot_macros.h" #include #include #include #include namespace godot { void PelletProjectile::_bind_methods() { #define CLASSNAME PelletProjectile } void PelletProjectile::_enter_tree() { this->distance_traveled = 0; } void PelletProjectile::_physics_process(double delta_time) { GDGAMEONLY(); float const speed = this->data->get_projectile_speed()->sample(distance_traveled / this->data->get_range()); this->distance_traveled += speed; Vector3 const next_position{this->get_global_position() + this->get_global_transform().basis.get_column(2) * speed}; if(this->check_hit(next_position) || this->distance_traveled > this->data->get_range()) this->return_to_pool(); else this->set_global_position(next_position); } bool PelletProjectile::check_hit(Vector3 next_position) { Ref query{PhysicsRayQueryParameters3D::create(this->get_global_position(), next_position, 0b101)}; Dictionary hit = this->get_world_3d()->get_direct_space_state()->intersect_ray(query); if(hit.is_empty()) return false; Node *collider = Object::cast_to(hit.get("collider", nullptr)); if(collider == nullptr) return false; IHealthEntity *health_entity = dynamic_cast(collider); if(health_entity == nullptr) return true; health_entity->get_health()->damage(this->data->get_damage()); return true; } }