#include "unit.hpp" #include "goap/goal.hpp" #include "godot_cpp/variant/callable_method_pointer.hpp" #include "godot_cpp/variant/utility_functions.hpp" #include "utils/godot_macros.hpp" #include void Unit::_bind_methods() { #define CLASSNAME Unit } void Unit::_enter_tree() { GDGAMEONLY(); this->agent = this->get_node("NavigationAgent3D"); this->planner = this->get_node("Planner"); this->world_state = this->get_node("ActorWorldState"); this->world_state->connect("attention_changed", callable_mp(this, &Unit::stop_plan)); } void Unit::_process(double delta_time) { } void Unit::stop_plan() { if(this->is_queued_for_deletion()) return; this->current_plan.clear(); if(this->state && !this->state->is_queued_for_deletion()) this->destroy_state(); this->state = nullptr; } void Unit::plan_for_marker(GoalMarker *marker) { this->destroy_state(); this->world_state->set_target_node(marker); this->plan_for_goal(marker->get_goal()); } void Unit::plan_for_goal(gd::Ref goal) { this->current_plan = this->planner->plan_for_goal(goal); this->next_action(); } UnitWorldState *Unit::get_world_state() const { return this->world_state; } void Unit::destroy_state() { if(this->state == nullptr || this->state->is_queued_for_deletion() || !this->state->is_inside_tree()) return; this->state->queue_free(); this->state = nullptr; } void Unit::state_finished() { if(this->current_plan.is_empty()) this->emit_signal("goal_finished"); this->next_action(); } void Unit::next_action() { if(this->state != nullptr && !this->state->is_queued_for_deletion()) this->destroy_state(); this->state = nullptr; if(this->current_plan.is_empty()) return; this->state = this->current_plan.get(0)->get_apply_state(this->world_state); if(state == nullptr) { this->stop_plan(); gd::UtilityFunctions::push_error("Plan failed to be executed, abandoning"); return; } this->current_plan.remove_at(0); this->add_child(this->state); this->state->connect("state_finished", this->on_state_finished); this->state->connect("state_failed", this->on_plan_failed); } void Unit::replan_goal() { this->plan_for_goal(this->current_goal); }