feat: implemented avoidance and exposed speed settings to editor
This commit is contained in:
		
							parent
							
								
									fb9417a1d8
								
							
						
					
					
						commit
						2134fcae92
					
				| 
						 | 
					@ -1,11 +1,13 @@
 | 
				
			||||||
#include "enemy_wretched.h"
 | 
					#include "enemy_wretched.h"
 | 
				
			||||||
#include "scene/animation/animation_player.h"
 | 
					#include "scene/animation/animation_player.h"
 | 
				
			||||||
 | 
					#include "wave_survival/macros.h"
 | 
				
			||||||
#include "wave_survival/npc_unit.h"
 | 
					#include "wave_survival/npc_unit.h"
 | 
				
			||||||
#include "wave_survival/patrol_path.h"
 | 
					#include "wave_survival/patrol_path.h"
 | 
				
			||||||
#include "wave_survival/player_body.h"
 | 
					#include "wave_survival/player_body.h"
 | 
				
			||||||
#include "wave_survival/state_machine.h"
 | 
					#include "wave_survival/state_machine.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void EnemyWretched::_bind_methods() {
 | 
					void EnemyWretched::_bind_methods() {
 | 
				
			||||||
 | 
						BIND_PROPERTY(Variant::FLOAT, chase_speed);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void EnemyWretched::on_child_entered(Node *node) {
 | 
					void EnemyWretched::on_child_entered(Node *node) {
 | 
				
			||||||
| 
						 | 
					@ -16,6 +18,7 @@ void EnemyWretched::on_child_entered(Node *node) {
 | 
				
			||||||
		this->anim = cast_to<AnimationPlayer>(node->get_node(NodePath("AnimationPlayer")));
 | 
							this->anim = cast_to<AnimationPlayer>(node->get_node(NodePath("AnimationPlayer")));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void EnemyWretched::ready() {
 | 
					void EnemyWretched::ready() {
 | 
				
			||||||
	fsm->add_state(memnew(WretchedPatrolState));
 | 
						fsm->add_state(memnew(WretchedPatrolState));
 | 
				
			||||||
	fsm->add_state(memnew(WretchedChaseState));
 | 
						fsm->add_state(memnew(WretchedChaseState));
 | 
				
			||||||
| 
						 | 
					@ -38,6 +41,14 @@ void EnemyWretched::_notification(int what) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void EnemyWretched::set_chase_speed(float speed) {
 | 
				
			||||||
 | 
						this->chase_speed = speed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float EnemyWretched::get_chase_speed() const {
 | 
				
			||||||
 | 
						return this->chase_speed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AnimationPlayer *EnemyWretched::get_anim() const {
 | 
					AnimationPlayer *EnemyWretched::get_anim() const {
 | 
				
			||||||
	return this->anim;
 | 
						return this->anim;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -66,6 +77,10 @@ void WretchedPatrolState::set_patrol_target(Vector3 path_point) {
 | 
				
			||||||
	get_nav()->set_target_position(path_point + get_target()->get_unit_offset_3d());
 | 
						get_nav()->set_target_position(path_point + get_target()->get_unit_offset_3d());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void WretchedPatrolState::on_velocity_calculated(Vector3 direction) {
 | 
				
			||||||
 | 
						get_target()->set_movement_direction(Vector2{ direction.x, direction.z } / get_target()->get_movement_speed());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WretchedPatrolState::enter_state() {
 | 
					void WretchedPatrolState::enter_state() {
 | 
				
			||||||
	this->path = get_target()->get_unit()->get_patrol_path();
 | 
						this->path = get_target()->get_unit()->get_patrol_path();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,6 +91,7 @@ void WretchedPatrolState::enter_state() {
 | 
				
			||||||
		Vector3 const nav_target{ this->path->get_closest_point(get_target()->get_global_position(), &this->path_point) };
 | 
							Vector3 const nav_target{ this->path->get_closest_point(get_target()->get_global_position(), &this->path_point) };
 | 
				
			||||||
		set_patrol_target(nav_target);
 | 
							set_patrol_target(nav_target);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						get_nav()->connect("velocity_computed", this->mp_on_velocity_calculated);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WretchedPatrolState::process(double delta) {
 | 
					void WretchedPatrolState::process(double delta) {
 | 
				
			||||||
| 
						 | 
					@ -84,11 +100,19 @@ void WretchedPatrolState::process(double delta) {
 | 
				
			||||||
			this->path_point += 1;
 | 
								this->path_point += 1;
 | 
				
			||||||
			set_patrol_target(this->path->point_at(this->path_point));
 | 
								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()) };
 | 
							Vector3 const direction{ get_target()->get_global_position().direction_to(get_nav()->get_next_path_position()).normalized() };
 | 
				
			||||||
		get_target()->set_movement_direction(Vector2{ direction.x, direction.z }.normalized());
 | 
							if (get_nav()->get_avoidance_enabled()) {
 | 
				
			||||||
 | 
								get_nav()->set_velocity(direction);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								on_velocity_calculated(direction);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void WretchedPatrolState::exit_state() {
 | 
				
			||||||
 | 
						get_nav()->disconnect("velocity_computed", this->mp_on_velocity_calculated);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String WretchedPatrolState::get_next_state() const {
 | 
					String WretchedPatrolState::get_next_state() const {
 | 
				
			||||||
	if (get_target()->get_unit()->is_aware_of_player()) {
 | 
						if (get_target()->get_unit()->is_aware_of_player()) {
 | 
				
			||||||
		return WretchedChaseState::get_class_static();
 | 
							return WretchedChaseState::get_class_static();
 | 
				
			||||||
| 
						 | 
					@ -97,9 +121,8 @@ String WretchedPatrolState::get_next_state() const {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void WretchedChaseState::enter_state() {
 | 
					void WretchedChaseState::enter_state() {
 | 
				
			||||||
	// TODO: replace this with a setting somewhere
 | 
						get_target()->set_movement_speed(get_target()->get_chase_speed());
 | 
				
			||||||
	get_target()->set_movement_speed(get_unit()->get_patrol_speed() * 2.f);
 | 
						get_nav()->set_max_speed(get_target()->get_chase_speed());
 | 
				
			||||||
	get_nav()->set_max_speed(get_unit()->get_patrol_speed() * 2.f);
 | 
					 | 
				
			||||||
	get_nav()->set_target_position(PlayerBody::get_singleton()->get_global_position());
 | 
						get_nav()->set_target_position(PlayerBody::get_singleton()->get_global_position());
 | 
				
			||||||
	get_anim()->play("ready"); // TODO: replace this with "run"
 | 
						get_anim()->play("ready"); // TODO: replace this with "run"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,9 +18,12 @@ protected:
 | 
				
			||||||
	void _notification(int what);
 | 
						void _notification(int what);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
						void set_chase_speed(float speed);
 | 
				
			||||||
 | 
						float get_chase_speed() const;
 | 
				
			||||||
	AnimationPlayer *get_anim() const;
 | 
						AnimationPlayer *get_anim() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
						float chase_speed{ 5.f };
 | 
				
			||||||
	StateMachine *fsm{ nullptr };
 | 
						StateMachine *fsm{ nullptr };
 | 
				
			||||||
	AnimationPlayer *anim{ nullptr };
 | 
						AnimationPlayer *anim{ nullptr };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -46,15 +49,18 @@ class WretchedPatrolState : public WretchedState {
 | 
				
			||||||
	GDCLASS(WretchedPatrolState, WretchedState);
 | 
						GDCLASS(WretchedPatrolState, WretchedState);
 | 
				
			||||||
	static void _bind_methods() {}
 | 
						static void _bind_methods() {}
 | 
				
			||||||
	void set_patrol_target(Vector3 path_point);
 | 
						void set_patrol_target(Vector3 path_point);
 | 
				
			||||||
 | 
						void on_velocity_calculated(Vector3 direction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	virtual void enter_state() override;
 | 
						virtual void enter_state() override;
 | 
				
			||||||
	virtual void process(double delta) override;
 | 
						virtual void process(double delta) override;
 | 
				
			||||||
	virtual String get_next_state() const override;
 | 
						virtual String get_next_state() const override;
 | 
				
			||||||
 | 
						virtual void exit_state() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	int path_point{ 0 };
 | 
						int path_point{ 0 };
 | 
				
			||||||
	PatrolPath *path{ nullptr };
 | 
						PatrolPath *path{ nullptr };
 | 
				
			||||||
 | 
						Callable mp_on_velocity_calculated{ callable_mp(this, &self_type::on_velocity_calculated) };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class WretchedChaseState : public WretchedState {
 | 
					class WretchedChaseState : public WretchedState {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,10 +11,10 @@ void EnemyBody::ready() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void EnemyBody::physics_process(double delta) {
 | 
					void EnemyBody::physics_process(double delta) {
 | 
				
			||||||
	GETSET(velocity, {
 | 
						GETSET(velocity, {
 | 
				
			||||||
		velocity = Vector3{ this->movement_direction.x, velocity.y, this->movement_direction.y };
 | 
							velocity = Vector3{ this->movement_direction.x * this->movement_speed, velocity.y, this->movement_direction.y * this->movement_speed };
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	if (!get_velocity().is_zero_approx()) {
 | 
						if (!this->movement_direction.is_zero_approx()) {
 | 
				
			||||||
		look_at(get_global_position() + get_velocity());
 | 
							look_at(get_global_position() + Vector3{ this->movement_direction.x, 0.f, this->movement_direction.y });
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	move_and_slide();
 | 
						move_and_slide();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NpcUnit::_bind_methods() {
 | 
					void NpcUnit::_bind_methods() {
 | 
				
			||||||
	BIND_HPROPERTY(Variant::OBJECT, patrol_path, PROPERTY_HINT_NODE_TYPE, "PatrolPath");
 | 
						BIND_HPROPERTY(Variant::OBJECT, patrol_path, PROPERTY_HINT_NODE_TYPE, "PatrolPath");
 | 
				
			||||||
 | 
						BIND_PROPERTY(Variant::FLOAT, patrol_speed);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NpcUnit::on_npc_awareness_changed(bool value) {
 | 
					void NpcUnit::on_npc_awareness_changed(bool value) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ private:
 | 
				
			||||||
	bool aware_of_player{ false };
 | 
						bool aware_of_player{ false };
 | 
				
			||||||
	Vector<EnemyBody *> npcs{};
 | 
						Vector<EnemyBody *> npcs{};
 | 
				
			||||||
	PatrolPath *patrol_path{ nullptr };
 | 
						PatrolPath *patrol_path{ nullptr };
 | 
				
			||||||
	float patrol_speed{ 3.f };
 | 
						float patrol_speed{ 1.f };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // !NPC_UNIT_H
 | 
					#endif // !NPC_UNIT_H
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ size = Vector3(0.37524414, 0.64245605, 0.38867188)
 | 
				
			||||||
size = Vector3(0.24902344, 0.42858887, 0.2619629)
 | 
					size = Vector3(0.24902344, 0.42858887, 0.2619629)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[sub_resource type="BoxShape3D" id="BoxShape3D_yvqru"]
 | 
					[sub_resource type="BoxShape3D" id="BoxShape3D_yvqru"]
 | 
				
			||||||
size = Vector3(0.86776733, 0.107666016, 0.11816406)
 | 
					size = Vector3(0.35500336, 0.107666016, 0.11816406)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="wretched" instance=ExtResource("1_w0sx6")]
 | 
					[node name="wretched" instance=ExtResource("1_w0sx6")]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@ func _on_health_status_death() -> void:
 | 
				
			||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_ng1ul"]
 | 
					[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_ng1ul"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="EnemyWretched" type="EnemyWretched"]
 | 
					[node name="EnemyWretched" type="EnemyWretched"]
 | 
				
			||||||
 | 
					chase_speed = 2.0
 | 
				
			||||||
script = SubResource("GDScript_qot2n")
 | 
					script = SubResource("GDScript_qot2n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="wretched" parent="." instance=ExtResource("1_qot2n")]
 | 
					[node name="wretched" parent="." instance=ExtResource("1_qot2n")]
 | 
				
			||||||
| 
						 | 
					@ -25,6 +26,9 @@ health = NodePath("../../../../../HealthStatus")
 | 
				
			||||||
[node name="Hitbox" parent="wretched/Character/Skeleton3D/HeadAttach" index="0" node_paths=PackedStringArray("health")]
 | 
					[node name="Hitbox" parent="wretched/Character/Skeleton3D/HeadAttach" index="0" node_paths=PackedStringArray("health")]
 | 
				
			||||||
health = NodePath("../../../../../HealthStatus")
 | 
					health = NodePath("../../../../../HealthStatus")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="CollisionShape3D" parent="wretched/Character/Skeleton3D/BoneAttachment3D/DamageBox" index="0"]
 | 
				
			||||||
 | 
					transform = Transform3D(1, -9.834766e-07, -2.454035e-06, 1.4305115e-06, 0.9999989, -8.145726e-06, 1.8983264e-06, 7.3344854e-06, 1, -0.20908, -5.9604645e-07, -4.7683716e-07)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
 | 
					[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
 | 
				
			||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
 | 
					transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
 | 
				
			||||||
shape = SubResource("CapsuleShape3D_ng1ul")
 | 
					shape = SubResource("CapsuleShape3D_ng1ul")
 | 
				
			||||||
| 
						 | 
					@ -35,6 +39,10 @@ unique_name_in_owner = true
 | 
				
			||||||
[node name="NavigationAgent3D" type="NavigationAgent3D" parent="."]
 | 
					[node name="NavigationAgent3D" type="NavigationAgent3D" parent="."]
 | 
				
			||||||
unique_name_in_owner = true
 | 
					unique_name_in_owner = true
 | 
				
			||||||
path_desired_distance = 0.25
 | 
					path_desired_distance = 0.25
 | 
				
			||||||
 | 
					avoidance_enabled = true
 | 
				
			||||||
 | 
					neighbor_distance = 10.0
 | 
				
			||||||
 | 
					time_horizon_agents = 0.7
 | 
				
			||||||
 | 
					debug_enabled = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="PlayerDetector" type="PlayerDetector" parent="."]
 | 
					[node name="PlayerDetector" type="PlayerDetector" parent="."]
 | 
				
			||||||
unique_name_in_owner = true
 | 
					unique_name_in_owner = true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,13 +5,22 @@
 | 
				
			||||||
[node name="NpcUnit" type="NpcUnit"]
 | 
					[node name="NpcUnit" type="NpcUnit"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="EnemyWretched" parent="." instance=ExtResource("1_l77gx")]
 | 
					[node name="EnemyWretched" parent="." instance=ExtResource("1_l77gx")]
 | 
				
			||||||
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, -0.9145346, 0.023195954, -0.63123465)
 | 
					transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, -1.1853347, 0.023195954, -0.8597343)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="EnemyWretched5" parent="." instance=ExtResource("1_l77gx")]
 | 
				
			||||||
 | 
					transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0.3304333, 0.023195954, 1.0620495)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="EnemyWretched6" parent="." instance=ExtResource("1_l77gx")]
 | 
				
			||||||
 | 
					transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0.026455224, 0.023195954, -1.7789332)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[node name="EnemyWretched7" parent="." instance=ExtResource("1_l77gx")]
 | 
				
			||||||
 | 
					transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 0.054681122, 0.023195954, -0.4100113)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="EnemyWretched2" parent="." instance=ExtResource("1_l77gx")]
 | 
					[node name="EnemyWretched2" parent="." instance=ExtResource("1_l77gx")]
 | 
				
			||||||
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 1.0534863, 0.023196908, -0.6773462)
 | 
					transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 1.3425274, 0.023196908, -0.9988682)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="EnemyWretched3" parent="." instance=ExtResource("1_l77gx")]
 | 
					[node name="EnemyWretched3" parent="." instance=ExtResource("1_l77gx")]
 | 
				
			||||||
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, -0.5066114, 0.023196908, 0.93247986)
 | 
					transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, -1.06229, 0.023196908, 0.46605587)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[node name="EnemyWretched4" parent="." instance=ExtResource("1_l77gx")]
 | 
					[node name="EnemyWretched4" parent="." instance=ExtResource("1_l77gx")]
 | 
				
			||||||
transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 1.3384295, 0.023197861, 0.74458694)
 | 
					transform = Transform3D(-1, 0, -8.742278e-08, 0, 1, 0, 8.742278e-08, 0, -1, 1.1567543, 0.023197861, 0.23159564)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue