80 lines
2.3 KiB
C++
80 lines
2.3 KiB
C++
#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 <godot_cpp/classes/navigation_agent3d.hpp>
|
|
|
|
void Unit::_bind_methods() {
|
|
#define CLASSNAME Unit
|
|
}
|
|
|
|
void Unit::_enter_tree() { GDGAMEONLY();
|
|
this->agent = this->get_node<gd::NavigationAgent3D>("NavigationAgent3D");
|
|
this->planner = this->get_node<goap::Planner>("Planner");
|
|
this->world_state = this->get_node<UnitWorldState>("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<goap::Goal> 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);
|
|
}
|