103 lines
3.2 KiB
C++
103 lines
3.2 KiB
C++
#include "enemy_wretched.h"
|
|
#include "wave_survival/npc_unit.h"
|
|
#include "wave_survival/patrol_path.h"
|
|
#include "wave_survival/player_body.h"
|
|
#include "wave_survival/state_machine.h"
|
|
|
|
void EnemyWretched::_bind_methods() {
|
|
}
|
|
|
|
void EnemyWretched::ready() {
|
|
if (StateMachine * fsm{ cast_to<StateMachine>(get_node(NodePath("%StateMachine"))) }) {
|
|
fsm->add_state(memnew(WretchedPatrolState));
|
|
fsm->add_state(memnew(WretchedChaseState));
|
|
fsm->add_state(memnew(WretchedAttackState));
|
|
}
|
|
}
|
|
|
|
void EnemyWretched::_notification(int what) {
|
|
if (Engine::get_singleton()->is_editor_hint()) {
|
|
return;
|
|
}
|
|
switch (what) {
|
|
default:
|
|
return;
|
|
case NOTIFICATION_READY:
|
|
ready();
|
|
return;
|
|
}
|
|
}
|
|
|
|
void WretchedState::set_target(Node *node) {
|
|
this->target = cast_to<EnemyWretched>(node);
|
|
this->nav = this->target->get_nav();
|
|
this->unit = this->target->get_unit();
|
|
}
|
|
|
|
EnemyWretched *WretchedState::get_target() const {
|
|
return this->target;
|
|
}
|
|
|
|
NpcUnit *WretchedState::get_unit() const {
|
|
return this->unit;
|
|
}
|
|
|
|
NavigationAgent3D *WretchedState::get_nav() const {
|
|
return this->nav;
|
|
}
|
|
|
|
void WretchedPatrolState::set_patrol_target(Vector3 path_point) {
|
|
get_nav()->set_target_position(path_point + get_target()->get_unit_offset_3d());
|
|
}
|
|
|
|
void WretchedPatrolState::enter_state() {
|
|
this->path = get_target()->get_unit()->get_patrol_path();
|
|
|
|
float const max_speed{ get_unit()->get_patrol_speed() };
|
|
get_target()->set_movement_speed(max_speed);
|
|
get_nav()->set_max_speed(max_speed);
|
|
Vector3 const nav_target{ this->path->get_closest_point(get_target()->get_global_position(), &this->path_point) };
|
|
set_patrol_target(nav_target);
|
|
}
|
|
|
|
void WretchedPatrolState::process(double delta) {
|
|
if (get_nav()->is_navigation_finished()) {
|
|
this->path_point += 1;
|
|
set_patrol_target(this->path->point_at(this->path_point));
|
|
}
|
|
Vector3 const direction{ get_target()->get_global_position().direction_to(get_nav()->get_next_path_position()) };
|
|
get_target()->set_movement_direction(Vector2{ direction.x, direction.z }.normalized());
|
|
}
|
|
|
|
String WretchedPatrolState::get_next_state() const {
|
|
if (get_target()->get_unit()->is_aware_of_player()) {
|
|
return WretchedChaseState::get_class_static();
|
|
}
|
|
return get_class();
|
|
}
|
|
|
|
void WretchedChaseState::enter_state() {
|
|
// TODO: replace this with a setting somewhere
|
|
get_target()->set_movement_speed(get_unit()->get_patrol_speed() * 2.f);
|
|
get_nav()->set_max_speed(get_unit()->get_patrol_speed() * 2.f);
|
|
get_nav()->set_target_position(PlayerBody::get_singleton()->get_global_position());
|
|
}
|
|
|
|
void WretchedChaseState::process(double delta) {
|
|
// TODO: optimize this with some checks to avoid re-pathing every frame
|
|
get_nav()->set_target_position(PlayerBody::get_singleton()->get_global_position());
|
|
Vector3 const direction{ get_target()->get_global_position().direction_to(get_nav()->get_next_path_position()) };
|
|
get_target()->set_movement_direction(Vector2{ direction.x, direction.z }.normalized());
|
|
}
|
|
|
|
String WretchedChaseState::get_next_state() const {
|
|
if (get_target()->get_global_position().distance_to(PlayerBody::get_singleton()->get_global_position()) < 2.f) {
|
|
return WretchedAttackState::get_class_static();
|
|
}
|
|
return get_class();
|
|
}
|
|
|
|
String WretchedAttackState::get_next_state() const {
|
|
return WretchedChaseState::get_class_static();
|
|
}
|