#include "rts_states.hpp" #include "utils/util_functions.hpp" #include #include #include void MoveTo::_bind_methods() {} void MoveTo::_ready() { this->parent_unit = Object::cast_to(this->get_parent()); this->agent = this->get_node("../NavigationAgent3D"); if(this->target_node == nullptr) { this->state_ended(); gd::UtilityFunctions::push_warning("failed to start MoveTo state due to missing target"); return; } this->agent->connect("velocity_computed", this->nav_velocity_computed); this->calculate_path(); gd::UtilityFunctions::print(this->parent_unit->get_path(), " MoveTo ", this->target_node->get_path()); } void MoveTo::_end_state() { this->agent->disconnect("velocity_computed", this->nav_velocity_computed); this->agent->set_target_position(this->parent_unit->get_global_position()); } void MoveTo::_process(double delta_time) { gd::Vector3 const pos = this->parent_unit->get_global_position(); gd::Vector3 const target = this->agent->get_next_path_position(); gd::Vector3 const direction = (target - pos).normalized(); this->agent->set_velocity(direction); bool const navigation_finished{this->agent->is_navigation_finished()}; if(this->is_action_done_interrupt() || navigation_finished) this->state_ended(); if((utils::time_seconds() - this->last_repath) > this->get_repath_interval()) this->calculate_path(); } void MoveTo::_physics_process(double delta) { this->parent_unit->move_and_slide(); } void MoveTo::calculate_path() { gd::Vector3 const target_pos{this->target_node->get_global_position()}; this->agent->set_target_position(target_pos); this->last_repath = utils::time_seconds(); this->target_position_at_last = target_pos; } void MoveTo::on_velocity_computed(gd::Vector3 vel) { gd::Vector3 const pos{this->parent_unit->get_global_position()}; gd::Vector3 const target_dir{(this->agent->get_next_path_position() - pos).normalized()}; // recalculate if avoidance is causing the motion to lock up if(target_dir.dot(vel.normalized()) < 0.25f) this->calculate_path(); } float MoveTo::target_delta_position() const { return this->target_position_at_last .distance_to(this->target_node->get_global_position()); } float MoveTo::distance_to_target() const { return this->target_position_at_last .distance_to(this->parent_unit->get_global_position()); } double MoveTo::get_repath_interval() const { float const target_delta_position{this->target_delta_position()}; if(target_delta_position == 0.f) return INFINITY; else return gd::Math::max(gd::Math::min(double(this->distance_to_target()), 5.0) - target_delta_position, 0.2); } void Activate::_bind_methods() {} void Animate::_bind_methods() {} void Animate::_ready() { this->anim = this->get_node("../AnimationPlayer"); this->anim->play(this->animation); if(!this->anim->has_animation(this->animation)) this->state_ended(); } void Animate::_process(double delta_time) { bool const animation_finished{!this->anim->is_playing() || this->anim->get_current_animation() != this->animation}; if(this->is_action_done_interrupt() || animation_finished) this->state_ended(); } void Animate::_end_state() { this->anim->stop(); }