authority/modules/authority/party_member_states.cpp
2026-01-18 23:26:41 +01:00

84 lines
3 KiB
C++

#include "party_member_states.h"
#include "authority/nav_marker.h"
#include "authority/player_character.h"
#include "core/config/engine.h"
#include "core/error/error_macros.h"
#include "core/templates/vector.h"
void PartyMemberFollow::_bind_methods() {}
void PartyMemberFollow::process_position_target() {
Vector3 const marker_position{ this->claimed_marker->get_global_position() };
Vector3 const nav_target{ this->nav->get_target_position() };
Vector3 const global_position{ get_character()->get_global_position() };
if (global_position.distance_squared_to(marker_position) < 0.5) {
return;
}
if (nav_target.distance_squared_to(marker_position) > 0.25) {
this->nav->set_target_position(marker_position);
}
if (this->nav->is_navigation_finished()) {
return;
}
Vector3 velocity{ global_position.direction_to(this->nav->get_next_path_position()) };
velocity.y = 0;
if (this->nav->get_avoidance_enabled()) {
this->nav->set_velocity(velocity * get_character()->get_data()->get_speed());
} else {
push_movement_direction(velocity * get_character()->get_data()->get_speed());
}
}
void PartyMemberFollow::push_movement_direction(Vector3 velocity) {
get_character()->set_movement(Vector2{ velocity.x, velocity.z });
}
void PartyMemberFollow::_notification(int what) {
if (Engine::get_singleton()->is_editor_hint()) {
return;
}
switch (what) {
default:
return;
case NOTIFICATION_READY:
this->nav = cast_to<NavigationAgent3D>(get_parent()->get_node(NodePath("%NavigationAgent3D")));
ERR_FAIL_COND_EDMSG(this->nav == nullptr, "PartyMemberFollow cannot initialise without a navigation agent");
return;
case NOTIFICATION_PROCESS:
process_position_target();
return;
}
}
PackedStringArray PartyMemberFollow::get_configuration_warnings() const {
PackedStringArray warnings{ super_type::get_configuration_warnings() };
if (!get_parent()->has_node(NodePath("%NavigationAgent3D")) || !cast_to<NavigationAgent3D>(get_parent()->get_node(NodePath("%NavigationAgent3D")))) {
warnings.push_back("PartyMemberFollow expects a scene sibling of type NavigationAgent3D named with unique name '%NavigationAgent3D'");
}
return warnings;
}
void PartyMemberFollow::state_entered() {
Vector<NavMarker *> const &markers{ PlayerCharacter::get_singleton()->get_party_follow_markers() };
for (NavMarker *marker : markers) {
if (marker->get_claimed() == nullptr) {
marker->set_claimed(get_character());
this->claimed_marker = marker;
if (this->nav->get_avoidance_enabled()) {
this->nav->connect("velocity_computed", callable_mp(this, &self_type::push_movement_direction));
}
set_process(true);
return;
}
}
ERR_FAIL_EDMSG("PartyMemberFollow could not find an unclaimed player follow marker");
set_state_active(false);
}
void PartyMemberFollow::state_exited() {
if (this->claimed_marker) {
this->claimed_marker->set_claimed(nullptr);
this->nav->disconnect("velocity_computed", callable_mp(this, &self_type::push_movement_direction));
set_process(false);
}
}